Can anyone help explain this weird example on Javascript?

I have been learning Javascript for 3 months, but when it comes to scoping, Javascript really puzzles me. Can anyone help explain the under hood of the following three examples(they have puzzled me a long time and I can’t find an answer by google)? Why they produce complete different results?

Example 1.
I created a global variable named myArray and directly changed its value with a function. Everything is going on as expected. I changed the value of ‘myArray’.

var myArray = [1, 2, 3, 4, 5];

function alterArray(){
  myArray = [5, 4, 3, 2, 1]
  return myArray; 
}

alterArray();
console.log(myArray);  //-> Array(5)[ 5, 4, 3, 2, 1 ]

Example 2.
To make the alterArray function more efficient, I added a parameter to it so that the function can change any global variable into an array [5, 4, 3, 2, 1]. Then the function just doesn’t work. myArray is still [1, 2, 3, 4, 5]. Why? What happened?

var myArray = [1, 2, 3, 4, 5];

function alterArray(arr){
  arr = [5, 4, 3, 2, 1];
  return arr;
}

alterArray(myArray);
console.log(myArray); //--> Array(5)[ 1, 2, 3, 4, 5 ]

Example 3.
I changed arr = [5, 4, 3, 2, 1]; into arr[0] = "number one"; (inspired by an exercise in chapter 4 Eloquent Javascript) in the function. And the function works again! Why? Why the function doesn’t work when I assign myArray a complete new value via the parameter, but works well when I only change part of myArray via the parameter?

var myArray = [1, 2, 3, 4, 5];

function alterArray(arr){
  arr[0] = "number one";
  return arr;
}

alterArray(myArray);
console.log(myArray); //--> Array(5)[ number one, 2, 3, 4, 5 ]

So, you need to understand that when you are passing that array as a parameter, you are not passing the array itself, but the address that points to it, aka passing by reference. This is very important.

In example two, what you did is create a completely new array, [5, 4, 3, 2, 1], with a new address and assigned it into the variable arr, which overwrites the address held by arr but doesn’t overwrite the address held by myArray. So now there are two arrays.

In example three, arr[0] tells it not to create a new array, but to go to the address of arr (which is the same address of myArray) and alter the first element.

It’s confusing, but makes perfect sense once you understand.

3 Likes

Thank you so much for your immediate help, Kevin.

So in Example 3, when the function is executed, I’m passing the address of myArray to parameter arr, which means at that moment both myArray and arr are pointing to the same bits stored in the memory. So when arr[0] = "number one" is executed, the execution happens directly on the same value myArray holds through that address.

In Example 2, before arr = [5, 4, 3, 2, 1] is executed, both myArray and arr are still pointing to the same value stored in the memory. But when arr = [5, 4, 3, 2, 1] is executed, I’m telling javascript to assign a completely new array to arr (just like from arr = myArray to arr = anotherArray), so arr gets a new address pointing to a new value, which means at that moment the connection between parameter arr and myArray are cut off. That’s why myArray is not changed at all.

1 Like

That’s a good explanation. It seems like magic in JS. Having done a language like C, where you manupulate addresses directly, this is all obvious. It’s somewhat hidden in JS, but you’re getting the hang of it now.

Thank you so much! I have been stuck here for a long time.