2

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 ]
Meng
  • 45
  • 3
  • That middle one throws you for a loop, eh? This is an example of JavaScript `passing a reference`, rather than `passing by reference`, from what I understand. That second example you provided means you are changing the reference of the `arr` variable to a new value. You aren't changing the thing it originally referenced to a new value, if that makes sense. It isn't a pure `pass by reference` situation like OOP languages. – adprocas Apr 12 '18 at 19:29
  • This is a legit duplicate, but I feel bad for someone who doesn't already understand reading that mess and coming away with clear understanding. I think the best answer from that article is this one: https://stackoverflow.com/a/3638034/294949. But I think this article does a better job explaining. (Walk through it carefully) https://hackernoon.com/grasp-by-value-and-by-reference-in-javascript-7ed75efa1293 – danh Apr 12 '18 at 20:02

1 Answers1

2

First thing you've to understand scope

  1. a variable declared outside any function has global scope and is accessible from anywhere in the file.
  2. When a variable is declared inside a function, it's function scoped, that means, it can only be accessed within the function.
  3. In JavaScript ES5 variable declared as var x follow above 2 rules. In JavaScript ES6 you can also declared variable as let x = 5 and const x = 5, these declarations are block scoped, which means these are only accessible within a block(e.g. if block)

coming to the point.

When you pass a variable as an argument

var x = 5;
change (x){ // here you've passed the value of x to the function, value of x is copied to new variable x inside the function.
  x = 3; // this x is not the same as above declared x
}
 change (x);
//In this example you've declared a new variable called x and initialised it with the value of global x.  
//So when you're assigning 3 to the `x` in line `x=3` you're changing the value of local variable, not the global.

In your first example you're not coping the value of global array to a new array, instead you're changing its value directly.

When a variable is found, JS interpreter looks for it's definition inside the local context, in this case, inside the function. If it doesn't find it's definition, it goes to the upper level (global level). In this case the interpreter already found the definition of x inside the function, so it didn't looked for global declaration and changed the local variable.

var x = 5;
change();
  x = 3; // here I haven't passed it as argument, so this x is not a copy of global x, it is the original global x
}
// The interpreter looked for definition of x inside the function, it didn't find. So it looked for global declaration and found it and finally changed the global variable

The 3rd way is passing the variable as an argument and changing it. It's not that completed as it sounds.

var x = 5; //global declaration
change(x){ //remember this x is different then the above. Now this x holds 5, as the value of global variable x is copied into it.
  x = 3; // now we changed the local variable
  return x; // the function is returning the value of x to the caller. So we need to collect the returned value when we call the function
}

//call the function
x = change(x); // same as x = change(5)
// Here global value got copied to the local variable and it got changed inside the function. The changed value was returned back.
// so we collected the changed value with x = function call
Community
  • 1
  • 1
surjit
  • 338
  • 4
  • 15