【问题标题】:Does forEach() bind by reference?forEach() 是否通过引用绑定?
【发布时间】:2014-07-20 18:36:14
【问题描述】:
var arr = ['Foo'];

arr.forEach(function(item){
  console.log(item);
  item = 'Lorem';
  console.dir(arr[0]);

});

for (var item in arr){
  arr[item] = 'Ipsum';
  console.dir(arr[0]);
}

如上面的代码所示,我注意到更改传递给forEach() 回调的项的值不会导致迭代对象改变。

使用for...in 当然可以。

为什么会这样?我应该如何更改数组中的值?

我发现 MDN 上的主题很混乱

【问题讨论】:

  • for..in 中访问属性的顺序完全取决于实现。 forEach 只访问从 0 到 length 的数字属性,并且严格按照数字顺序访问,它与值无关。指向 MDN 的链接已损坏,也许您的意思是 this one
  • 将您的代码放在这里而不是其他网站吗?

标签: javascript foreach pass-by-reference


【解决方案1】:

使用 for...in 当然可以。

不,它没有。你的forEach 循环相当于这个for...in 循环(除了顺序):

for (var index in arr) {
  var item = arr[index];
  console.log(item);
  item = 'Lorem';
  console.dir(arr[0]);
}

您是否看到数组也没有被修改?那是因为 JavaScript 总是pass-by-value,并且有一个非常简单的规则需要牢记:

为变量赋值从不改变另一个变量或数据结构的值。

这意味着,为item 分配一个新值,不能更改arr 的元素。如果要修改数组,则必须通过为索引分配值来直接对其进行变异,即

arr[index] = 'foo';

【讨论】:

  • 我发现这听起来令人困惑,因为对象通过引用传递
  • @Sprotenwels:不,这是正确的。 JavaScript 只有传值。 JavaScript 中唯一的值是原语和指向对象的指针。 “对象”不是值,不能“通过”。
  • @Sprotenwels:这很令人困惑,但 pass-by-reference 具有不同且非常具体的含义。您可以在 Wikipedia 文章中阅读有关内容。还可以看看 pass-by-sharing 部分,它更接近 JS 的工作原理,但它不是一个很常用的术语。
【解决方案2】:

在您的情况下,item 变量是按值传递的,因为它是原始值。如果它是一个 json 对象,并且您将更改其属性之一,它将反映在原始列表中。

在这种情况下,您可以使用forEach 具有的其他参数。例如:

arr.forEach(element, index, array) {
    ...
}

使用这些参数,您可以直接影响array[index]

【讨论】:

  • 正是我想要的。谢谢!
【解决方案3】:

注意forEach 中的回调有三个参数。第二个是当前元素的索引,第三个是数组本身。如果要修改数组,请使用这两个参数。

【讨论】:

    猜你喜欢
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多