带对象的Array.prototype.fill()传递引用而不是新实例

时间:2016-02-23 13:09:37

标签: javascript arrays

只是一个小问题。

我有点玩弄并试图实例化一个新的长度x数组,其中该数组的所有元素初始化为值y

var arr = new Array(x).fill(y);

如果y的值不是对象,则此方法很有效。 意思是y是一个对象,以下是真实的:

var arr = new Array(2).fill({});
arr[0] === arr[1]; //is true;
arr[0].test = 'string';
arr[1].test === 'string'; //is also true;

有没有办法说明在使用fill-function时应该为每个元素创建一个新对象?或者我应该将其转换为循环?

提前致谢!

7 个答案:

答案 0 :(得分:39)

您可以先使用任何值fill数组(例如undefined),然后您就可以使用map

var arr = new Array(2).fill().map(u => ({}));
var arr = new Array(2).fill().map(Object);

答案 1 :(得分:16)

接受的答案是好的,并且在90%的案例中都有效。

但是,如果您正在制作高性能的JS应用程序,并且如果您使用大型/大型数组, Array.map(..)会在两者中创建大的重载 - 内存和处理器的使用,因为它创建了一个数组副本。

我建议使用经典的 for 循环:

    a = new Array(ARRAY_SIZE);
    for (var i = 0; i < ARRAY_SIZE; i++) {
        a[i] = [];
    }

我测试了三种替代方案并得到了这个:

  • 建议答案( 11倍!!! 较慢):

    a = new Array(ARRAY_SIZE).fill().map(u => { return []; });
    
  • 简单循环(最快):

    a = new Array(ARRAY_SIZE);
    for (var i = 0; i < ARRAY_SIZE; i++) {
        a[i] = [];
    }
    
  • forEach( 2x时间更慢):

    a = new Array(ARRAY_SIZE).fill();
    a.forEach((val, i) => {
        a[i] = [];
    })
    

PS。我使用this fiddle进行测试。

答案 2 :(得分:8)

一个高效的解决方案: Array.from({ length: 5 }, () => new Object())

答案 3 :(得分:1)

Ilias Karim的答案非常出色。我只是做了以下事情:

a = Array.from({length:l}, () => new Array(c).fill(prefix));

创建指定大小的预填充2D数组,以l乘c填充前缀。现在,我的代码可以填充2D矩阵中需要非前缀值的插槽。

答案 4 :(得分:1)

最短的可能:

let node =  [...Array(2)].map(_=>({}))
console.log(node)

答案 5 :(得分:0)

您还可以通过以下解决方法解决此问题。

var arr = new Array(2).fill({});
arr = JSON.parse(JSON.stringify(arr));

答案 6 :(得分:0)

我写了一篇关于此的博文:http://www.samhenderson.xyz/posts/12

但是 TLDR 是,如果您想避免链接多个函数,例如fillmap。并且想避免写循环,那么可以使用:

const array = Array.from({ length: 2 },()=>({}))

对于数组数组:

const array = Array.from({ length: 2 },()=>([]))