Javascript function scoping and hoisting

后端 未结 18 2922
孤街浪徒
孤街浪徒 2020-11-21 04:20

I just read a great article about JavaScript Scoping and Hoisting by Ben Cherry in which he gives the following example:

var a = 1;

function b() {
    a =          


        
18条回答
  •  隐瞒了意图╮
    2020-11-21 05:21

    Long Post!

    But it will clear the air!

    The way Java Script works is that it involves a two step process:

    1. Compilation(so to speak) - This step registers variables and function declarations and their respective scope. It does not involve evaluating function expression: var a = function(){} or variable expression (like assigning 3 to x in case of var x =3; which is nothing but the evaluation of R.H.S part.)

    2. Interpreter: This is the execution/evaluation part.

    Check the output of below code to get an understanding:

    //b() can be called here!
    //c() cannot be called.
    console.log("a is " + a);
    console.log("b is " + b);
    console.log("c is " + c);
    var a = 1;
    console.log("Now, a is " + a);
    var c = function() {};
    console.log("Now c is " + c);
    
    function b() {
      //cannot write the below line:
      //console.log(e); 
      //since e is not declared.
      e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
      console.log("e is " + e) //  works!
      console.log("f is " + f);
      var f = 7;
      console.log("Now f is " + f);
      console.log("d is " + d);
      return;
    
      function d() {}
    }
    b();
    console.log(a);

    Lets break it:

    1. In the compilation phase, 'a' would be registered under global scope with value 'undefined'. Same goes for 'c', its value at this moment would be 'undefined' and not the 'function()'. 'b' would be registered as a function in the global scope. Inside b's scope, 'f' would be registered as a variable which would be undefined at this moment and function 'd' would be registered.

    2. When interpreter runs, declared variables and function() (and not expressions) can be accessed before the interpreter reaches the actual expression line. So, variables would be printed 'undefined' and declared anonymous function can be called earlier. However, trying to access undeclared variable before its expression initialisation would result in an error like:

    console.log(e)
    e = 3;

    Now, what happens when you have variable and function declaration with same name.

    Answer is - functions are always hoisted before and if the same name variable is declared, it is treated as duplicate and ignored. Remember, order does not matter. Functions are always given precedence. But during evaluation phase you can change the variable reference to anything (It stores whatever was the last assignment) Have a look at the below code:

    var a = 1;
    console.log("a is " + a);
    
    function b() {
      console.log("a inside the function b is " + a); //interpreter finds                                'a' as function() in current scope. No need to go outside the scope to find 'a'.
      a = 3; //a changed
      console.log("Now a is " + a);
      return;
    
      function a() {}
    }
    var a; //treated as duplicate and ignored.
    b();
    console.log("a is still " + a + " in global scope"); //This is global scope a.

提交回复
热议问题