1

I create an empty 3x3x1 3D array

[
  [[],[],[]],
  [[],[],[]],
  [[],[],[]]
]

Now, The element at position arr[1][1] is [], So, If I execute arr[1][1].push(1) it should insert 1 on position arr[1][1]

There are 2 methods for creating an empty 3x3x1 array in JS, Here is the code,

var arr1 = [...new Array(3)].map(e => [...new Array(3)].fill([]));
var arr2 = [[[],[],[]],[[],[],[]],[[],[],[]]];
arr1[1][1].push(1);
arr2[1][1].push(1);
console.log(arr1)
console.log(arr2)

ie. Through shortcut and another manually, both arr1 and arr2 should be identical, so should be the output, But the output is as follows,

[[[], [], []], [[1], [1], [1]], [[], [], []]]

[[[], [], []], [[], [1], []], [[], [], []]]

Why is it that first array gives such output? Aren't both identical?

I want the output to be of the 2nd form, If this is a wrong way to create an empty 3x3x1 array, please suggest a method such that it gives expected output.

James Z
  • 12,209
  • 10
  • 24
  • 44
  • Does this answer your question? [Array.fill gives same object repeated. why?](https://stackoverflow.com/questions/43294552/array-fill-gives-same-object-repeated-why) – Ivar Oct 06 '20 at 18:27
  • @Ivar If broken down, yes. But I think if someone has such Problem, they will not know fill() is the culprit. They might search with this phrase. That does answer the question, I agree. – Abhishek Choudhary Oct 06 '20 at 18:34
  • That's why we keep questions like this one around [as a signpost](https://stackoverflow.com/help/duplicates). :) – Ivar Oct 06 '20 at 18:38
  • 1
    @Ivar Okay, That's a good thing, I had really tough time finding why I had this problem and it was so unclear that we can't phrase it properly and they will just describe the bigger picture, It might help people stuck in similar situations, Thank you. – Abhishek Choudhary Oct 06 '20 at 18:45

2 Answers2

3

Use one more nested map. I think that fill call will fill the first map with the same array in each of the 2nd dimension instead of a unique one which means the 2nd dimension all reference the same array.

The docs from fill even note that the value will be the exact same:

Value to fill the array with. (Note all elements in the array will be this exact value.)

Also (array is an object):

If the first parameter is an object, each slot in the array will reference that object.

const arr1 = [...new Array(3)].map(e => [...new Array(3)].fill([]));
const arr2 = [[[],[],[]],[[],[],[]],[[],[],[]]];
const arr3 = [...new Array(3)].map(() => [...new Array(3)].map(() => []));

arr1[1][1].push(1);
arr2[1][1].push(1);
arr3[1][1].push(1);

console.log(JSON.stringify(arr1)); // [[[],[],[]],[[1],[1],[1]],[[],[],[]]]
console.log(JSON.stringify(arr2)); // [[[],[],[]],[[],[1],[]],[[],[],[]]]
console.log(JSON.stringify(arr3)); // [[[],[],[]],[[],[1],[]],[[],[],[]]]

In other words:

const expandedArr1 = [...new Array(3)].map(() => {
  /*
   * From MDN fill documentation:
   * Value to fill the array with. (Note all elements in the array will be this exact value.)
   */
  return [...new Array(3)].fill([]); // Every element will get this exact value (reference)
});

// They are the same reference:
console.log(expandedArr1[1][1] === expandedArr1[1][2]);
zero298
  • 25,467
  • 10
  • 75
  • 100
2

The reason this happens is because fill method fills the "exact value" in all the three.

MDN : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill See the Note in Parameter value description.

var arr1 = [...new Array(3)].map(e => [...new Array(3)].map(e=>[])); // Note that i have used a map with a function returning an array([]) instead of your fill method
var arr2 = [[[],[],[]],[[],[],[]],[[],[],[]]];
arr1[1][1].push(1);
arr2[1][1].push(1);
console.log(arr1)
console.log(arr2)
Sachin Nayak
  • 1,041
  • 9
  • 17