先来看问题,我想创建一个二维数组,初始化为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]]