Array.fill 重复给出相同的对象。为什么?

IT技术 javascript ecmascript-6
2021-02-27 13:36:40

var arr = new Array(4).fill({});

arr[2].status = true;

console.log(arr[0].status); 

为什么数组填充在所有索引中填充相同的对象?

2个回答

.fill将在数组的每个段上插入完全相同的对象(相同的实例)。
这就是为什么这样做.fill(Math.random)会返回一个始终填充相同数字的数组。

你可以这样做来获得你想要的:

new Array(4).fill().map(() => ({}));

为了解释问题代码中发生的事情,让我们将其转换为 ES5 代码:

var arr = new Array(4);  // new Array(4)
var obj = new Object();  // *1: with this object instance
for(i = 0; i < 4; i++) { // .fill( *1 )
  arr[i] = obj;
}

如您所见,我们将相同的对象实例 ( obj)分配给数组实例的每个单元格。

这是相同的原理:

const obj = {};
const a = obj;
const b = obj;

a.foo = true;

下定a.foo === b.foo决心true

fill 也是 ES2015 的一部分而不是 ES5
2021-04-24 13:36:40
是的,这是有效的,+1。请添加值是对象引用并且每个项目都是引用的想法。
2021-04-26 13:36:40
我真的很喜欢“解释幕后发生的事情......” 注意:var obj = new Object(); {}不是新的,没有理由使用new Object()而不是{}在 ES5 版本中。
2021-04-26 13:36:40
我认为它提供了更好的“正在创建新实例”的想法
2021-05-04 13:36:40
@FezVrasta:够公平的。
2021-05-07 13:36:40

fill重复传递给它这种情况下的值是一个对象引用。该引用的每个副本都指向同一个对象,因此您得到的是:

       +−−−−−−−−−−−+
arr--->| (数组) |
       +−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−+
       | 0 |−−+−+−+−>| (对象) |
       | 1 |−/ / / +−−−−−−−−−−−−−−−+
       | 2 |--/ / | 状态:真实 |
       | 3 |−−−/ +−−−−−−−−−−−−−−−+
       +−−−−−−−−−−−+       

如果需要单独的对象,则需要创建多个对象。最简单的方法当然是:

var arr = [{}, {}, {}, {}];

例子:

var arr = [{}, {}, {}, {}];
arr[2].status = true;
console.log("arr[0].status", arr[0].status);
console.log("arr[2].status", arr[2].status);

如果你想用可变长度来做:

由于您使用的是Array.fill,我假设您使用的是 ES2015(又名“ES6”)功能(但请参阅下文了解不带 polyfill 的 ES5 兼容解决方案)。你可以通过Array.from回调来做到这一点

const arr = Array.from({length:4}, () => ({})); 
arr[2].status = true;
console.log("arr[0].status", arr[0].status);
console.log("arr[2].status", arr[2].status);

这给了你:

                    
       +−−−−−−−−−−−+       
arr--->| (数组) |       
       +−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−+
       | 0 |−−−−−−−−−>| (对象) |
       | 1 |−−−−−+ +−−−−−−−−−−−−−−−+
       | 2 |−−−+ |   
       | 3 |-+ | | +−−−−−−−−−−−−−−−−+
       +−−−−−−−−−−+ | | +−−>| (对象) |
                   | | +−−−−−−−−−−−−−−−−+
                   | |     
                   | | +−−−−−−−−−−−−−−−−+
                   | +−−−−->| (对象) |
                   | +−−−−−−−−−−−−−−−−+
                   | | 状态:真实 |
                   | +−−−−−−−−−−−−−−−−+
                   |                      
                   | +−−−−−−−−−−−−−−−−+
                   +−−−−−−−>| (对象) |
                            +−−−−−−−−−−−−−−−−+

Array.from如果你愿意,你可以在 ES5 上使用 polyfill来做到这一点,只需使用function() { return {}; }代替() => ({})。)


在 ES5 中,如果你需要一个可变长度,最简单的可能就是一个循环:

var arr = [];
for (var i = 0; i < 4; ++i) {
    arr[i] = {};
}
arr[2].status = true;
console.log("arr[0].status", arr[0].status);
console.log("arr[2].status", arr[2].status);

当然,你可以把它放在一个辅助函数中。