Array.prototype.fill() with object passes reference and not new instance
I was toying a bit and was trying to instantiate a new array of length x
, where all elements of that array were 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 if 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?
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);
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 an array.
I recommend to use the classic for loop:
a = new Array(ARRAY_SIZE);
for (var i = 0; i < ARRAY_SIZE; i++) {
a[i] = [];
}
// or it's one line alternative
for (var i = 0, a = []; i < ARRAY_SIZE; a[i++] = []);
I tested six alternatives and got this:
-
Array.map(), as proposed above (11x times!!! slower):
a = new Array(ARRAY_SIZE).fill().map(u => { return []; });
-
for loop, the best one (fastest):
// Standard multi-line way a = new Array(ARRAY_SIZE); for (var i = 0; i < ARRAY_SIZE; i++) { a[i] = []; } // One line syntax for (var i = 0, a = []; i < ARRAY_SIZE; a[i++] = []);
-
forEach (6x time slower):
a = new Array(ARRAY_SIZE).fill(); a.forEach((val, i) => { a[i] = []; })
[UPDATE 2020-08-27] One more way proposed by Ilias Karim below
-
Array.from (30x times!!! slower) - apparently worse in terms of performance, despite the nicest syntax :(
a = Array.from({ length: ARRAY_SIZE }, () => []);
-
[..Array(..)] (5x times!!! slower)
a = [...Array(ARRAY_SIZE)].map(_=>([]))
-
Array.push(..), second place in terms of performance (2x times!!! slower)
let a = [], total = ARRAY_SIZE; while(total--) a.push([]);
PS. I used this fiddle for tests.