Array.Prototype.Fill() With Object Passes Reference and Not New Instance

Array.prototype.fill() with object passes reference and not new instance

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);

JavaScript - why Array.prototype.fill actually fills a pointer of object when filling anything like 'new Object()'

I am wondering why it's happening?

Array#fill takes the value you give it as the first argument, and fills the array with copies of that value.

The value you're giving it is a reference to an array, so naturally what it gives you back is an array filled with copies of that reference. Not copies of the array, copies of the reference.

E.g., it behaves this way for exactly the same reason this code:

var a = new Array(10);
var b = a;

...leaves us with a and b both referring to the same array (both containing the same value; a reference to the single array we've created).

Let's throw some Unicode-art at it:

After this code runs:

var a = new Array(10);
var b = a;

we have this in memory (minus a few irrelevant details):


a:Ref89895−−−+
|
| +−−−−−−−−−−−−−−−+
+−−−−−>| array |
| +−−−−−−−−−−−−−−−+
| | length: 10 |
b:Ref89895−−−+ +−−−−−−−−−−−−−−−+

a and b contain a reference, which I've shown here as Ref89895 although we never see the actual value. That's what's copied by b = a, not the array itself.

Similarly, when you do:

var matrix = new Array(10).fill(new Array(10), 0);

you end up with


+−−−−−−−−−−−−−−−+
matrix:Ref89895−−−>| array |
+−−−−−−−−−−−−−−−+
| length: 10 |
| 0: Ref55462 |--\
| 1: Ref55462 |--\\
| 2: Ref55462 |--\\\
| 3: Ref55462 |--\\\\ +−−−−−−−−−−−−−−−+
| 4: Ref55462 |---+++++->| array |
| 5: Ref55462 |--///// +−−−−−−−−−−−−−−−+
| 6: Ref55462 |--//// | length: 10 |
| 7: Ref55462 |--/// +−−−−−−−−−−−−−−−+
| 8: Ref55462 |--//
| 9: Ref55462 |--/
+−−−−−−−−−−−−−−−+

To create a 10-place array where each of the 10 places is itself a 10-place array of 0, I'd probably use either Array.from or fill with map:

// Array.from
var matrix = Array.from({length: 10}, function() {
return new Array(10).fill(0);
});

// fill and map
var matrix = new Array(10).fill().map(function() {
return new Array(10).fill(0);
});

or in ES2015:

// Array.from
let matrix = Array.from({length: 10}, () => new Array(10).fill(0));

// fill and map
let matrix = new Array(10).fill().map(() => new Array(10).fill(0));

Array.fill(Array) creates copies by references not by value

You could use Array.from() instead:

Thanks to Pranav C Balan in the comments for the suggestion on further improving this.

let m = Array.from({length: 6}, e => Array(12).fill(0));

m[0][0] = 1;

console.log(m[0][0]); // Expecting 1

console.log(m[0][1]); // Expecting 0

console.log(m[1][0]); // Expecting 0

Why does Array(n).fill([]) not the same as hardcoding the array or using a for loop to create that array?

as described here

the fill method of Array fills the array (or a given range of indices in the array) with the same value

that means when you write the line Array(3).fill([]) it actually puts the same array created using [] in all the indices of the array, so editing the array in one place, affects all indices (since they all point to the same array [])

How do I use array.fill for creating an array of objects?

Note: not sure what is happening in running a snippet, but that ref business does not happen in the real world

as per Xufox comment: /**ref:2**/ means “reference to element 2 of the array”, since the console feature of Stack Snippets can’t know whether you’ve got an infinitely nested structure, so instead the ref comments (and id comments which aren’t used in this case) are used

The real problem with

const concise = new Array(9).fill({});

IS that all 9 entries will "refer" to the same object - see the output

const concise = new Array(9).fill({}); // {} 

concise[0].a='hello world';

console.log(JSON.stringify(concise))

Array.prototype.fill({}) references

You are filling each position in the array with the same reference of an object, it is the same as

let a = {};

const b = a;

a.hi = 'hi';

console.log(b);

What am I missing in this Javascript Array behavior?

function na(){
return Array(2).fill(Array(2))
}

na() fills the empty Array(2) with shallow copies of the second Array(2) object.

As a result changing values in any of the clones changes the Array's value everywhere.

a = Array(5).fill(Array(3))

a[0][0] = 1
a[0][1] = 2
a[0][2] = 3

console.log(JSON.stringify(a))


Related Topics



Leave a reply



Submit