Search code examples
javascriptfunctionscoping

Weird examples in javascript, why I can't reassign a global variable's value through a function's parameter?


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 ]

Solution

  • 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