Strange behavior of an array filled with Array.prototype.fill ()

I am encountering something that I don't understand with an array. In fact, I created an array that I filled with empty submatrices to get a 2D matrix. But when I manipulate the array, it does not behave as I expected.

var arr = new Array(5);
arr.fill([]);
arr[2].push("third rank item");
console.log(arr);

//[ [ 'third rank item' ],
//  [ 'third rank item' ],
//  [ 'third rank item' ],
//  [ 'third rank item' ],
//  [ 'third rank item' ] ]

Every light on this subject will be welcome.

+4
source share
6 answers

This is the same old problem when arrays (and objects in general) are references, not values.

In particular, when you execute arr.fill([]), you take one single empty array and use it to populate the parent.

I like to say:

var arr = new Array(5);
arr[0] = arr[1] = arr[2] = arr[3] = arr[4] = [];

! , , , ( )

, . - :

Array.apply(null, Array(5)).map(function() {return [];});

, () 5 () [].

EDIT: , . @torazaburo, Array.from Array.apply(null, Array(5)).map, :

Array.from( new Array(5), function() { return []; } );
+5

, array.fill, ,

, while:

var arr = [];
var n = 5
while(n--)
  arr[n] = []

arr[2].push("third rank item");
console.log(arr);
Hide result

2:
lodash, _.map, ( init)

var arr =_.map(new Array(5), (x => []))

arr[2].push("third rank item");
console.log(arr)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
Hide result
+1

ECMA doc Array.prototype.fill .

, k <

Pk - ToString (k).

setStatus Set (O, Pk, value, true).

ReturnIfAbrupt (setStatus).

k 1.

"" - . . , .

+1

This is the reason for the appeal. An array is an object type, and an object works on their links when you fill your array with [] or new Array()fill run only ones and put the same array in all indexes, so when you update the submatrix, all are updated.

Decision:

let arr = new Array(5).fill(0).map(ele => ele = []); arr[2].push("something");

OR

let arr = Array.of([], [], [], []); arr[2].push("something");

Result: as expected, only 2 indexes are updated arr.

+1
source

You can try this,

var arr = new Array(5);
var i = 0;
while (i < arr.length)
  arr.fill([], i++);
arr[2].push("third rank item");
console.log(arr);
Run codeHide result
0
source

Try this, it is a quick solution for you in one line.

var arr = new Array(5);
arr = Array.from(arr, x => []);
arr[2].push("third rank item");
console.log(arr);
Run codeHide result
0
source

Source: https://habr.com/ru/post/1663623/