I was studying JS when faced an unexpected behavior by me. It's probably something related to local vs global scope, however I could not find the answer. Here how it goes:
I have two arrays, one empty and another with some values. If a push the one with values inside the empty one, then updating the values using .push() method, it will update the array inside the other as well:
let newArr = [];
let valueArr = [0,0];
newArr.push(valueArr);
// newArr = [[0,0]]
console.log(newArr);
valueArr.push(0);
// newArr = [0,0,0] --> updates it
console.log(valueArr);
However, if a now try to update the variable using = assignment, it won't change the array inside newArr
let newArr = [];
let valueArr = [0,0];
newArr.push(valueArr);
// newArr = [[0,0]]
console.log(newArr);
valueArr = [0,0,0];
// newArr = [[0,0]] --> does not update it
console.log(newArr);
Does anyone know why pushing has this behavior and reassigning does not? It's due local/global scope or when I reassign the valueArr variable, the newArr variable loses its track?
This is not related to local/global scope.
TLDR
When you call push on an array, you add items to the existing array. When you use an assignment, you create a new array that has nothing to do with the one that was stored in the variable previously.
Detailed
Here's what's happening in the code:
Step 1. let valueArr = [0,0];
When you assign an array to a variable, there are two things happening:
[0,0])valueArr variable saves a reference to the created arrayStep 2. newArr.push(valueArr);
Then, you push valueArr array into the newArr array. Now newArr[0] contains an element with the same reference as valueArr. They both point to the [0,0] array.
Step 3. valueArr.push(0);
In this step, we push an element to the array that valueArr references. Since newArr references the same array, newArr[0] gets updated too.
Step 4. valueArr = [0,0,0];
Here we repeat step 1. Create a new array and save its reference to the valueArr. The thing is that we change the reference stored in the valueArr, but newArr[0] still points to the old array. This is why you don't see any updates: it's a completely different array.
This would be a good start if you want to learn more about reference types: https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0
If you want to update newArr, do so explicitly:
valueArr = [0,0,0];
newArr[0] = valueArr;
You need to distinguish between an object and a reference to object. An object is a "thing". But a reference to an object is just a way to describe which "thing" you are talking about.
A variable is a way to explicitly reference an object using a name. But you can also reference objects in other ways, such as (as you discovered) through an array index.
A couple of important things to keep clear:
=) operator explicitly creates a reference to an object. You can later refer to that object through the variable name.[ ]) on the right hand side of the assignment operator.a.push(b) implicitly creates a reference from some index of a to the object being referenced by b at that point in time.===) operator to determine whether two expressions refer to the same object./*
We create a new array, lets call it Object 1.
We can refer to that array using the variable name `a`.
*/
let a = [];
/*
We create a new array, lets call it Object 2.
We refer to that array using the variable name `b`.
*/
let b = [0];
/*
When we call `push` we are implicitly creating a
new reference: from a[0] to Object 2.
*/
a.push(b);
/*
`a[0]` and `b` are both referring to
the *exact same* object: Object 2.
*/
console.log("Are `a[0]` and `b` the same object:", a[0] === b); // -> true
/*
We create a new array, lets call it Object 3.
We explicitly tell Javascript to use `b` to
refer to Object 3 from this point forward.
*/
b = [2];
/*
Notice that `a[0]` still refers to Object 2.
*/
console.log("Are `a[0]` and `b` the same object:", a[0] === b); // -> false
/*
We can explicitly tell javascript to update `a` by
using the assignment operator.
*/
a[0] = b;
console.log("Are `a[0]` and `b` the same object:", a[0] === b); // -> true