var arr = new Array(4).fill({});
arr[2].status = true;
console.log(arr[0].status);
为什么数组填充在所有索引中填充相同的对象?
答案 0 :(得分:10)
.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
。
答案 1 :(得分:6)
fill
重复您传递的值。在这种情况下,值是一个对象引用。该引用的每个副本都引用同一个对象,因此您得到的是:
+−−−−−−−−−+ arr−−−>| (array) | +−−−−−−−−−+ +−−−−−−−−−−−−−−+ | 0 |−−+−+−+−>| (object) | | 1 |−/ / / +−−−−−−−−−−−−−−+ | 2 |−−/ / | status: true | | 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”)功能(但请参阅下面的ES5兼容解决方案,不使用polyfill)。您可以通过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−−−>| (array) | +−−−−−−−−−+ +−−−−−−−−−−−−−−+ | 0 |−−−−−−−−>| (object) | | 1 |−−−−−+ +−−−−−−−−−−−−−−+ | 2 |−−−+ | | 3 |−+ | | +−−−−−−−−−−−−−−+ +−−−−−−−−−+ | | +−−>| (object) | | | +−−−−−−−−−−−−−−+ | | | | +−−−−−−−−−−−−−−+ | +−−−−>| (object) | | +−−−−−−−−−−−−−−+ | | status: true | | +−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−+ +−−−−−−>| (object) | +−−−−−−−−−−−−−−+
(如果您愿意,可以在ES5上使用Array.from
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);
当然,你可以把它放在辅助函数中。