Array.fill repeats the same object. What for?

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

arr[2].status = true;

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

Run codeHide result


why is filling the array filling the same object at all indices?

+3


source to share


2 answers


.fill

will insert the same exact object (same instance) into every segment of the array. That is why it .fill(Math.random)

returns an array always filled with the same number.

You can do this to get what you want:

new Array(4).fill().map(() => ({}));

      

To explain what's going on under the hood in your question code, let me convert it 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 one object instance ( obj

) to each cell of the array instance.

This is the same principle why:

const obj = {};
const a = obj;
const b = obj;

a.foo = true;

      

Makes a a.foo === b.foo

resolution true

.

+8


source


fill

repeats the value that you pass. The value in this case is an object reference. Each copy of this link refers to the same object, so you end up with:

       + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
arr βˆ’βˆ’βˆ’> | (array) |
       + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ + +
       | 0 | βˆ’βˆ’ + - + - + -> | (object) |
       | 1 | - / / / + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
       | 2 | βˆ’βˆ’ / / | status: true |
       | 3 | βˆ’βˆ’βˆ’ / + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
       + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +       

If you want separate objects, you need to create multiple objects. The easiest way, 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);
      

Run codeHide result


If you want to do it with variable length:

Since you are using Array.fill

, I assume you are using ES2015 (aka "ES6") features (but see below for an ES5 compliant solution without polyfills). You can do it 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);
      

Run codeHide result


This gives you:

                    
       + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +       
arr βˆ’βˆ’βˆ’> | (array) |       
       + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ + +
       | 0 | βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’> | (object) |
       | 1 | βˆ’βˆ’βˆ’βˆ’βˆ’ + + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
       | 2 | βˆ’βˆ’βˆ’ + |   
       | 3 | - + | | + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
       + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ + | | + βˆ’βˆ’> | (object) |
                   | | + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
                   | |     
                   | | + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
                   | + βˆ’βˆ’βˆ’βˆ’> | (object) |
                   | + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
                   | | status: true |
                   | + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
                   |                      
                   | + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +
                   + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’> | (object) |
                            + βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’βˆ’ +

(You can do this with an Array.from

ES5 polyfill if you want, just use function() { return {}; }

instead () => ({})

.)


In ES5, if you want 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);
      

Run codeHide result


You can of course add this to a helper function.

+4


source







All Articles