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

时间:2017-04-08 13:13:12

标签: javascript ecmascript-6

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

arr[2].status = true;

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

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

2 个答案:

答案 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);

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