Array.prototype.fill() with object passes referenc

2020-01-22 11:48发布

问题:

Just a small question.

I was toying a bit and was trying to instantiate a new array of lenght x, where all elements of that array where initialized to a value y

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

This works well if the value of y is anything other than an object. Meaning that is y is an object, the following is true:

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

Is there any way to state that a new object should be created for each element while using the fill-function? Or should I just convert it to a loop?

Thanks in advance!

回答1:

You can first fill the array with any value (e.g. undefined), and then you will be able to use map:

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


回答2:

The accepted answer is good, and would work in 90% of cases.

But if you are making high performance JS application, and if you work with big/huge arrays, Array.map(..) creates big overload in both - memory and processor use, as it creates a copy of array.

I recommend to use the classic for loop:

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

I tested three alternatives and got this:

  • Proposed answer (11x times!!! slower):

    a = new Array(ARRAY_SIZE).fill().map(u => { return []; });
    
  • Simple loop (fastest):

    a = new Array(ARRAY_SIZE);
    for (var i = 0; i < ARRAY_SIZE; i++) {
        a[i] = [];
    }
    
  • forEach (2x time slower):

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

PS. I used this fiddle for tests.



回答3:

One performant solution: Array.from({ length: 5 }, () => new Object())



回答4:

Shortest Possable:

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



回答5:

Ilias Karim's answer is most excellent. I just did the following:

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

to create a pre-filled 2D array of the specified size, l by c, filled with prefix. Now my code can fill in the slots in the 2D matrix that need non-prefix values.



回答6:

You could also solve this by the following workaround.

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