Array.prototype.map()可以改变它调用的数组吗?

apo*_*llo 5 javascript arrays

Mozilla说:

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

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

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

调用了数组映射.

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

因此,通过改变第三个参数,我们应该改变原始数组,但是以下两个片段会产生相互矛盾的结果:

情况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
Run Code Online (Sandbox Code Playgroud)

情况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
Run Code Online (Sandbox Code Playgroud)

显然,在第二种情况下,原始数组是变异的(迭代器只执行一次).但是我错过了什么?为什么冲突的结果呢?

Cer*_*nce 5

在案例1中,您只是重新分配 - 这突变是分开的.只有你有类似的语法才会发生变异obj.prop = <someExpression>.这就是你在案例2中所做的事情

_B.length = 0;
Run Code Online (Sandbox Code Playgroud)

内存中_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);
Run Code Online (Sandbox Code Playgroud)