Array.fill gives same object repeated. why? [duplicate]
var arr = new Array(4).fill({});
arr[2].status = true;
console.log(arr[0].status);
why is array fill filling same object in all indexes?
.fill
will insert the same exact object (same instance) on each segment of the array.
That's why doing .fill(Math.random)
will return an array filled with always the same number.
You can do this to obtain what you want:
new Array(4).fill().map(() => ({}));
To explain what's happening under the hood in your question's code, let's convert this to ES5 code:
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;
}
As you can see, we are assigning the same object instance (obj
) to each cell of the array instance.
This is the same principle of why:
const obj = {};
const a = obj;
const b = obj;
a.foo = true;
Makes a.foo === b.foo
resolve to true
.
fill
repeats the value you pass it. The value in this case is an object reference. Every copy of that reference refers to the same object, so what you're getting is:
+−−−−−−−−−+ arr−−−>| (array) | +−−−−−−−−−+ +−−−−−−−−−−−−−−+ | 0 |−−+−+−+−>| (object) | | 1 |−/ / / +−−−−−−−−−−−−−−+ | 2 |−−/ / | status: true | | 3 |−−−/ +−−−−−−−−−−−−−−+ +−−−−−−−−−+
If you want separate objects, you'll need to create multiple objects. The simplest way is, of course:
var arr = [{}, {}, {}, {}];
Example:
var arr = [{}, {}, {}, {}];
arr[2].status = true;
console.log("arr[0].status", arr[0].status);
console.log("arr[2].status", arr[2].status);
If you want to do it with a variable length:
Since you're using Array.fill
, I'm assuming you're using ES2015 (aka "ES6") features (but see below for an ES5-compatible solution without polyfills). You can do that via Array.from
with a callback:
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);
That gives you:
+−−−−−−−−−+ arr−−−>| (array) | +−−−−−−−−−+ +−−−−−−−−−−−−−−+ | 0 |−−−−−−−−>| (object) | | 1 |−−−−−+ +−−−−−−−−−−−−−−+ | 2 |−−−+ | | 3 |−+ | | +−−−−−−−−−−−−−−+ +−−−−−−−−−+ | | +−−>| (object) | | | +−−−−−−−−−−−−−−+ | | | | +−−−−−−−−−−−−−−+ | +−−−−>| (object) | | +−−−−−−−−−−−−−−+ | | status: true | | +−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−+ +−−−−−−>| (object) | +−−−−−−−−−−−−−−+
(You can do that with an Array.from
polyfill on ES5 if you like, just use function() { return {}; }
instead of () => ({})
.)
In ES5, if you need a variable length, the simplest thing is probably just a loop:
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);
You could put that in a helper function, of course.