请教一个关于JS语法的问题

今天排查自己用cocos开发的小游戏的bug时发现的一个问题。其实是关于js语法的,但是因为除了cocos论坛,不知道还有哪里可以讨论这种技术问题,所以只能发在这里,向各位大佬请教。
如下的一段代码:

  Test() {
    let array1 = new Array(5).fill({ a: 0 })
    let array2 = new Array(5).fill({ a: 0 })
    for (let i = 0; i < 5; i++) {
      setTimeout(() => {
        array1[i].a = i
        array2[i] = {a:i}
        console.warn("array = ", array1)
        console.warn("array2 = ", array2)
      }, 0.2 * i)
    }
  },

作用其实很简单,就是把array这个数组依次设置为{a:0}, {a:1}…
但是,如果采用第一种写法array1[i].a = i, 会发现代码完全执行完毕之后,最终array = [{a:4},{a:4},{a:4},{a:4},{a:4}]
如果是第二种写法array2[i] = {a:i}, 结果是符合预期的[{a:0},{a:1},{a:2},{a:3},{a:4}]

请问这是为什么啊?什么机制导致的会有这样的差异?
浏览器用的是chrome

let data = { a: 0 }
let array1 = new Array(5).fill(data)
data.a = 1;
console.log(array1)

你看下这段代码的结果,估计你就能想明白了。
你的array里是同一个对象啊

哦,明白了,原来如此。

谢谢

let array1 = new Array(5).fill({ a: 0 })
let array2 = new Array(5).fill({ a: 0 })
for (let i = 0; i < 5; i++) {
setTimeout(() => {
console.log(’------’,i);
array1[i].a = i
console.log("array = ", array1)
}, 0.2 * i);
}

有点疑惑,输出的i是0-4,但是为什么每次打印array1的a都是4,,,这个很奇怪

看二楼的回复啊,array1的元素其实都是同一个对象,最后一次赋值是4,所以显示4, 而array2每次赋值的都是一个新对象

这是js setTimeout 和js 指针的经典问题吧

造成这个的原因完全是由 Array.fill是浅拷贝造成的吧,和 js 闭包没有多大关系,for循环用的let ,所有问题不出在变量i上面,很少 fill 一个对象,:grinning: 受教了。

1赞

fill的对象是同一个对象的引用,如果需要这样使用的话可以这样new Array(5).fill(null).map((v)=>({a:0}))