JavsScript:别往Array.fill()方法传入对象

先来看问题,我想创建一个二维数组,初始化为0,某些条件下数值改为1.

// 初始化[[0,0],[0,0],[0,0]]
let array = new Array(3).fill([0,0]);
//改变array[1][0]的值为1
array[1][0] = 1;
// 理想结果:[[0,0],[1,0],[0,0]]
console.log(array);// [[1,0],[1,0],[1,0]]

很明显,结果和想像的很不一样,我只想改变array[1][0]的值,但结果是二维数组里面每个数组的都被动了。

查一下MDN文档

fill 方法是个可变方法, 它会改变调用它的 this 对象本身, 然后返回它, 而并不是返回一个副本。
当一个对象被传递给 fill方法的时候, 填充数组的是这个对象的引用。

看下面例子:

// Objects by reference.
var arr = Array(3).fill({}) // [{}, {}, {}];
// 需要注意如果fill的参数为引用类型,会导致都执行都一个引用类型
// 如 arr[0] === arr[1] 为true
arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]

也就是说,无论在fill()传入多少个对象,这些对象都是同一个,修改哪一个,都会全部被改了。

最后,补充一下fill的语法

arr.fill(value[, start[, end]]);

第一个参数value:用来填充数组元素的值。
第二个参数start (可选的): 起始索引,默认值为0。如果 start 是个负数, 则开始索引会被自动计算成为 length+start。
第三个参数end (可选的): 终止索引,默认值为 this.length。如果 end 是个负数, 则结束索引会被自动计算成为 length+end。

// MDN上的例子
[1, 2, 3].fill(4);               // [4, 4, 4]
[1, 2, 3].fill(4,0,3);         // [4, 4, 4],相当于[1, 2, 3].fill(4);

[1, 2, 3].fill(4, 1);            // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2);         // [1, 4, 3]
[1, 2, 3].fill(4, 3, 5);         // [1, 2, 3]

[1, 2, 3].fill(4, 1, 1);         // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3);         // [1, 2, 3]
[1, 2, 3].fill(4, NaN, NaN);     // [1, 2, 3]

[1, 2, 3].fill(4, 0, 1);          // [4, 2, 3]
[1, 2, 3].fill(4, -3, -2);       // [4, 2, 3],start=-3+3=0, end=-2+3=1, 相当于[1, 2, 3].fill(4, 0, 1);

回到开头的初始化方法

let array = new Array(3);
for(let i=0;i<3;i++){
    array[i] = [0,0];
};
array[1][0] = 1;
console.log(array);// [[0,0],[1,0],[0,0]]

你可能感兴趣的:(JavsScript:别往Array.fill()方法传入对象)