2

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?

Mushroomator
  • 6,516
  • 1
  • 10
  • 27
  • 2
    `valueArr.push(0);` pushes to the existing array, `valueArr = [0,0,0];` discards the previous reference and makes `valueArr` reference a completely new array. –  Apr 20 '22 at 16:57
  • 1
    The issue has nothing to do with scope. When you re-assign a variable value with `=`, the previous value is gone. – Pointy Apr 20 '22 at 17:00

2 Answers2

1

TLDR

If you want to update newArr, do so explicitly:

valueArr = [0,0,0]; 
newArr[0] = valueArr;

In depth explanation

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:

  1. The assignment(=) operator explicitly creates a reference to an object. You can later refer to that object through the variable name.
  2. A variable can refer to different objects over time (through repeated applications of the assignment operator).
  3. Arrays are JavaScript objects. You create a new array object every time you use square brackets ([ ]) on the right hand side of the assignment operator.
  4. a.push(b) implicitly creates a reference from some index of a to the object being referenced by b at that point in time.
  5. You can use the strict equality(===) 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
David Sainez
  • 6,446
  • 1
  • 22
  • 45
1

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:

  1. An array is getting created and saved in memory([0,0])
  2. The valueArr variable saves a reference to the created array

Step 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