2

let arr = [[1,2,3], [4,5,6], [7,8,9]]
arr[0][1] = 'X'
arr[1][1] = 'O'

console.log(arr);

I'm trying to work out a preliminary tic-tac-toe game and this method to create the table serves me fine.

Upon reading up on other methods to generate a matrix array table I found this

let newArr = new Array(3).fill(new Array(3))
newArr[0][1] = 'X'

console.log(newArr)

As I attempt to return newArr it actually replaces the entire column with 'X'.

Why is it doing that? I was thinking maybe during the stack it recognized I was naming the value of one undefined index and would just much rather do the same for the entire column but I cannot confirm.

Rajesh
  • 24,354
  • 5
  • 48
  • 79
jondub
  • 23
  • 3
  • And to explain why, `array.fill` expects 1 argument and it will fill the array with this element. Now objects are copied by reference, so when you pass object/array to it, you are filling all the values in an array with same reference. Hence, updating 1 value updates all values. – Rajesh Oct 16 '17 at 06:27
  • Thank you so much it makes perfect sense. Definitely not practical to apply Array.fill with the same reference object. – jondub Oct 16 '17 at 06:35
  • An alternate can be `Array.from({length: 3}, (x) => new Array(3))`, but this is an ES6 feature. Would work for you but use at your own risk – Rajesh Oct 16 '17 at 07:02

1 Answers1

1

Array#fill takes an object/primitive and uses it to fill all items. You have given an array into the function, array is a reference type, so it uses the same reference for all items, but the object is single. So why you get updated for all columns.

You can compare references to be sure that single is created and used for all items.

let newArr = new Array(2).fill(new Array(2));

console.log(newArr[0] === newArr[1]);

To create an array like you want, you can do

let newArr = Array.from({ length: 3 }, () => new Array(3));

newArr[0][1] = 'X';

console.log(newArr);
Suren Srapyan
  • 66,568
  • 14
  • 114
  • 112