0

I need to create an array of arrays. Every nested array should be filled with zeroes. I'v tried this:

let test = Array
  .from(
    new Array(8)
      .fill(
        new Array(8).fill(0)
      )
  );

But then I'd got issue with a reference. For example if I do this:
test[1][2] = 1;
then every nested array has value 1 at index 2:
console.log(test[2][2]) // 1

I came up with simple solution using a loop:

const testArray = new Array(8);

for (let i = 0; i < testArray.length; i++) {
  testArray[i] = new Array(8).fill(0);
}

Now it works and there's no issue with reference. But I don't understand why this issue occurred in the first try. Can someone be so kind and explain that to me?

Mateusz Witkowski
  • 1,646
  • 10
  • 24

2 Answers2

3

You're filling the array with 8 identical references to a single array, rather than 8 distinct references to 8 separate arrays. fill reuses the same value for each entry in the array it fills, so you get this:

+−−−−−−−−−−−−+
|  (array)   |
+−−−−−−−−−−−−+                           +−−−−−−−−−+
| 0: Ref2215 |−−−−−−−−+−+−+−+−+−+−+−−−−−>| (array) |
| 1: Ref2215 |−−−−−−−/ / / / / / /       +−−−−−−−−−+
| 2: Ref2215 |−−−−−−−−/ / / / / /        | 0: 0    |
| 3: Ref2215 |−−−−−−−−−/ / / / /         | 1: 0    |
| 4: Ref2215 |−−−−−−−−−−/ / / /          | 2: 0    |
| 5: Ref2215 |−−−−−−−−−−−/ / /           | ...     |
| 6: Ref2215 |−−−−−−−−−−−−/ /            +−−−−−−−−−+
| 7: Ref2215 |−−−−−−−−−−−−−+
+−−−−−−−−−−−−+

It doesn't matter which array slot you use, they all contain a reference to the same one array.

Your second code block creates separate arrays (I won't bother with the diagram :-)). Here's a slightly shorter way to do it:

let test = Array.from(
                Array(8),
                () => new Array(8).fill(0) // Mapping callback creates
           );                              // new array for every entry
                                           // in the outer array
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    That`s it. I've just found this on MDN docs: "When the fill method gets passed an object, it will copy the passed object, and fill the array with a reference to the copy". Thanks you. – Mateusz Witkowski Jan 21 '18 at 19:14
  • 2
    @MateuszWitkowski: Yikes, we should fix that then. `fill` absolutely does not "copy the object." – T.J. Crowder Jan 21 '18 at 19:15
  • How did you create that graph so swiftly? – guest271314 Jan 21 '18 at 19:24
  • 1
    I'm tolerably quick with `vim`. – T.J. Crowder Jan 21 '18 at 19:24
  • Thanks @T.J.Crowder I'm sorry that this question was marked as duplicate (I won't bother to argue against it). Especially that IMO your answer is more verbose and informative than the answers in the question that I supposedly duplicated. – Mateusz Witkowski Jan 21 '18 at 19:30
  • @MateuszWitkowski: Happy to help. Duplicate questions are not necessarily a bad thing. (They are sometimes, they aren't other times.) By asking the question a different way, duplicates create a larger target for searches to find. Then if duplicates are closed and point to a central answer, the system works well. (There's a lot more I'd do to the SO system in this regard, but...it isn't my system. :-) ) – T.J. Crowder Jan 21 '18 at 19:36
1

The reason is that the second new Array(8).fill(0) is referenced by all the cell of the parent Array(). You are creating it only once!

Instead, in your second try, you are creating it 8 times.