ES6 中 Array 的 fill() 方法

fill 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。

最近遇到的一个坑,其实也不算是坑,只是自己没有了解清楚就在用了。

以前在业务中声明数组变量时我都是使用的 var arr = [] 来声明,
这次兴起用了一次 var arr = new Array(8).fill([]) 声明并且填充内容时居然翻车了….


先来看下使用方法

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

fill 方法接受三个参数 value, start 以及 end,并且返回一个修改后的数组;

  • valut 用来填充数组元素的值, 如果不写则填充 undefined
  • startend 参数是可选的, 分别是 起始索引终止索引 ,默认值分别为 0this 对象的 length 属性值。
  • fill 方法是个可变方法, 它会改变调用它的 this 对象本身, 然后返回它, 而并不是返回一个副本

🌰🌰🌰 时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[1, 2, 3].fill(4);               // [4, 4, 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, 1, 1); // [1, 2, 3]

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

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

Array(3).fill(4); // [4, 4, 4]

// 还有一个MDN上的奇怪操作
[].fill.call({ length: 3 }, 4); // {0: 4, 1: 4, 2: 4, length: 3}

接下来就要提到我遇到坑了,
当使用fill方法填充一个对象时,比如说:

1
2
var arr = new Array(8).fill({ a: 1 })   
// [{a: 1}, {a: 1}, {a: 1}, {a: 1}, {a: 1}, {a: 1}, {a: 1}, {a: 1}]

然后我们修改其中任意子项的属性 a,然后输出他们

1
2
3
arr[0].a = 2
console.log(arr)
// [{a: 2}, {a: 2}, {a: 2}, {a: 2}, {a: 2}, {a: 2}, {a: 2}, {a: 2}]

可以看到他们全体都被修改了,对的,当一个对象(数组也一样)被传递给 fill 方法的时候, 填充数组的是这个对象的引用。

所以这次我自己 Debug 了3个小时都没发现的 问题 就是因为这!!

附: