 # Caution When Reinitializing Variables Inside a Loop

Caution When Reinitializing Variables Inside a Loop
0

#1

Tell us what’s happening:
If I don’t re-initialized “row = []” inside forLoop then
matrix = (3) [Array(6), Array(6), Array(6)].

I don’t understand how each array at each index has 6 elements in it because according to me it should be
matrix = (3) [Array(2), Array(4), Array(6)].

Correct me where I’m going wrong?

Your code so far

``````
function zeroArray(m, n) {
// Creates a 2-D array with m rows and n columns of zeroes
let newArray = [];
let row = [];
for (let i = 0; i < m; i++) {
// Adds the m-th row into newArray

for (let j = 0; j < n; j++) {
// Pushes n zeroes into the current row to create the columns
row.push(0);
}
// Pushes the current row, which now has n zeroes in it, to the array
newArray.push(row);
}
return newArray;
}

let matrix = zeroArray(3, 2);
console.log(matrix);
``````

User Agent is: `Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36`.

#2

This is a really good question and really well spotted.

You’re quite correct, according to the code it should be matrix = (3) [Array(2), Array(4), Array(6)].

I can’t tell you for sure what’s happening but I can tell you what it looks like - that push() isn’t just adding the numbers to newArray, it seems to be merging them in some way. Any changes you make to row seem to be reflected in newArray. This seems to be true even when row is defined in the for loop.

However, the two variables don’t seem to point at the same object (== comes back negative).

I think an afternoon with You Don’t Know Javascript may be called for.

#3

The answer lies in reference types, newArray is getting a reference to row pushed to it, when row updates it data it is reflected inside newArray because it’s data is just a pointer to row. The two arrays are not the same object, but the data inside newArray is a reference pointer to the row object. The loops has nothing to do with it.

``````const row = [0, 0];
const newArray = [];
newArray.push(row);
row.push(0,0)
newArray // is now [0, 0, 0, 0]
row.push('pass', 'by', 'reference')
newArray // is now [0, 0, 0, 0, "pass", "by", "reference"]
``````

#4

You need to reinitialize the `row` variable to output the expected results because inside both loops you are using a reference in memory where Javascript stores the row data.

Let me explain it by using your code:

The first time you push the row into `newArray` in the first “round”, you’re pushing a reference to the array, not just the values; in this case row is `[0,0]`. That’s fine so far. However, when you do this the second time, you would expect it to be pushing `[0,0,0,0]` at the end of `newArray`, leaving its value like this: `[[0,0],[0,0,0,0]]`, right? Wrong. Since you are using references, any time you change the length or values of the `row` array, you are also applying these changes to any variables referencing this array, like `newArray` (again, because it’s using references instead of values). So, when you push the `row` array into `newArray` the second time, the latter becomes `[[0,0,0,0][0,0,0,0]]`, and `[[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]]` the last time you do it.

How to solve this? Well, as you mentioned, you can reinitialize the variables inside the outer loop and it will work fine. You can also push a copy of `row` instead of the reference. Using the spread operator is quite straightforward, as you can see in the following modified snippet:

``````function zeroArray(m, n) {
let newArray = [];
let row = [];
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
row.push(Math.random());
}
newArray.push([...row]); // [...row] <-- Use of spread operator.
}
return newArray;
}

let matrix = zeroArray(3, 2);
console.log(matrix);
``````

Hope it helps