【问题标题】:Can Array.prototype.map() mutate the array it invokes on?Array.prototype.map() 可以改变它调用的数组吗?
【发布时间】:2018-12-17 04:17:49
【问题描述】:

Mozilla 说:

map 不会改变调用它的数组(尽管回调,如果 调用,可以这样做)。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

具体来说,回调传递的第三个参数是:

调用了数组映射。

我假设这意味着内存中的数组位置通过引用复制到回调中。

所以通过改变第三个参数,我们应该改变原始数组,但是下面两个 sn-p 给出的结果是冲突的:

案例1,重新赋值第三个参数并没有改变原始数组:

var A = [1, 2, 3];
A.map((v,i,_A) => { 
  console.log("_A is the array map invoked on: ", _A===A); // true
  _A = []; // reassign an empty array
  return v;
});
console.log("'A' did not mutate:", A) // [1, 2, 3] did not mutate

情况2,将第三个参数设置为零长度会改变原始数组:

var B = [1, 2, 3];
B.map((v,i,_B) => { 
  console.log("_B is the array map invoked on: ", _B===B); // true
  _B.length = 0; // clearing the array by setting it zero length
  return v;
});
console.log("'B' has mutated:", B) // [] mutated

很明显,在第二种情况下,原始数组发生了变异(迭代器只执行一次)。 但我错过了什么?为什么会出现矛盾的结果?

【问题讨论】:

  • 为什么将新值重新分配给指向源数组的Array.prototype.map 的第三个参数会更改源数组? AArray.prototype.map 的第三个参数是 2 个不同的变量

标签: javascript arrays


【解决方案1】:

在第 1 种情况下,您只是 重新分配 - 这与突变分开。仅当您具有 obj.prop = <someExpression> 之类的语法时,才会发生突变。这就是你在案例 2 中所做的

_B.length = 0;

内存中_B 引用的对象的.length 属性将发生突变。但是仅仅重新分配一个变量名,比如_A = [],不会改变_A之前碰巧引用的任何东西——之前_A引用的对象将被忽略(保持不变) ,并且将来在范围内对_A 的引用将引用刚刚分配给_A 的任何内容。

这与Array.prototype.map 没有任何关系 - 这与您在任何 Javascript 对象或变量名中看到的行为相同,例如:

const obj = { foo: 'foo' };
let anotherObj = obj; // references the original object
anotherObj = {};
// a new object is created in memory and assigned to the variable name `anotherObj`
// but this does not mutate whatever anotherObj happened to refer to before
console.log(obj);

【讨论】:

    【解决方案2】:

    在 JavaScript 中,事情并不完全是您可能熟悉的传递引用。在回调的本地范围内创建对 A 的引用的本地副本。有关更多信息,请参阅此答案:Does Javascript pass by reference?

    因此,当您将 _A 重新分配给一个空数组时,您只是告诉引用副本指向一个新的空数组。但是,对 A 的旧引用仍然存在并且未受影响。

    当你改变长度时,你实际上是在改变 _A 所指的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-19
      • 2019-06-01
      • 2016-04-15
      • 1970-01-01
      • 1970-01-01
      • 2014-03-17
      相关资源
      最近更新 更多