Javascript function scoping and hoisting

2018-12-31 00:31发布

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 = 10;
    return;

    function a() {}
}
b();
alert(a);

Using the code above, the browser will alert "1".

I'm still unsure why it returns "1". Some of the things he says come to mind like: All the function declarations are hoisted to the top. You can scope a variable using function. Still doesn't click for me.

14条回答
无色无味的生活
2楼-- · 2018-12-31 01:03

Function hoisting means that functions are moved to the top of their scope. That is,

function b() {  
   a = 10;  
   return;  
   function a() {} 
} 

will be rewritten by the interpeter to this

function b() {
  function a() {}
  a = 10;
  return;
}

Weird, eh?

Also, in this instance,

function a() {}

behaved the same as

var a = function () {};

So, in essence, this is what the code is doing:

var a = 1;                 //defines "a" in global scope
function b() {  
   var a = function () {}; //defines "a" in local scope 
   a = 10;                 //overwrites local variable "a"
   return;      
}       
b();       
alert(a);                 //alerts global variable "a"
查看更多
余生无你
3楼-- · 2018-12-31 01:06

Hoisting is behavioural concept of JavaScript. Hoisting (say moving) is concept that explains how and where variables should be declared.

In JavaScript, a variable can be declared after it has been used because Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter.

We encounter two types of hoisting in most cases.

1.Variable declaration hoisting

Lets understand this by this piece of code.

 a = 5; // Assign 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
 var a; // Declare a
  //output-> 5

Here declaration of variable a will be hosted to top invisibly by the javascript interpreter at the time of compilation. So we were able to get value of a. But this approach of declaration of variables is not recommended as we should declare variables to top already like this.

 var a = 5; // Assign and declare 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
  // output -> 5

consider another example.

  function foo() {
     console.log(x)
     var x = 1;
 }

is actually interpreted like this:

  function foo() {
     var x;
     console.log(x)
     x = 1;
  }

In this case x will be undefined

It does not matter if the code has executed which contains the declaration of variable. Consider this example.

  function foo() {
     if (false) {
         var a = 1;
     }
     return;
     var b = 1;
  }

This function turns out to be like this.

  function foo() {
      var a, b;
      if (false) {
        a = 1;
     }
     return;
     b = 1;
  }

In variable declaration only variable definition hoists, not the assignment.

  1. Function declaration hoisting

Unlike the variable hoisting the function body or assigned value will also be hoisted. Consider this code

 function demo() {
     foo(); // this will give error because it is variable hoisting
     bar(); // "this will run!" as it is function hoisting
     var foo = function () {
         alert("this would not run!!");
     }
     function bar() { 
         alert("this will run!!");
     }
 }
 demo();

Now as we understood both variable and function hoisting, let's understand this code now.

var a = 1;
function b() {
  a = 10;
  return;
   function a() {}
}
b();
alert(a);

This code will turn out to be like this.

var a = 1;                 //defines "a" in global scope
 function b() {  
   var a = function () {}; //defines "a" in local scope 
    a = 10;                 //overwrites local variable "a"
    return;      
 }       
 b();       
 alert(a); 

The function a() will have local scope inside b(). a() will be moved to top while interpreting the code with its definition (only in case of function hoisting) so a now will have local scope and therefore will not affect the global scope of a while having its own scope inside function b().

查看更多
泛滥B
4楼-- · 2018-12-31 01:11
  1. function declaration function a(){} is hoisted first and it behaves like var a = function () {};, hence in local scope a is created.
  2. If you have two variable with same name (one in global another in local), local variable always get precedence over global variable.
  3. When you set a=10, you are setting the local variable a , not the global one.

Hence, the value of global variable remain same and you get, alerted 1

查看更多
栀子花@的思念
5楼-- · 2018-12-31 01:14

scpope & closure & hoisting (var/function)

  1. scpope : the global var can be access in any place(the whole file scope), local var only can be accessed by the local scope(function/block scope)!
    Note: if a local variable not using var keywords in a function, it will become a global variable!
  2. closure : a function inner the other function, which can access local scope(parent function) & global scope, howerver it's vars can't be accessed by others! unless, your return it as return value!
  3. hoisting : move all declare/undeclare vars/function to the scope top, than assign the value or null!
    Note: it just move the declare,not move the value!

var a = 1;                
//"a" is global scope
function b() {  
   var a = function () {}; 
   //"a" is local scope 
   var x = 12; 
   //"x" is local scope 
   a = 10;
   //global variable "a" was overwrited by the local variable "a"  
   console.log("local a =" + a);
   return console.log("local x = " + x);
}       
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x = 
console.log(x);
// ReferenceError: x is not defined

查看更多
时光乱了年华
6楼-- · 2018-12-31 01:15

Its all depends on the scope of variable 'a'. Let me explain by creating scopes as images.

Here JavaScript will create 3 scopes.

i) Global scope. ii) Function b() scope. iii) Function a() scope.

enter image description here

Its clear when you call 'alert' method scope belongs to Global that time, so it will pick value of variable 'a' from Global scope only that is 1.

查看更多
永恒的永恒
7楼-- · 2018-12-31 01:16

It is happening because of the Variable name is same as the function name means "a". Thus due to Javascript hoisting it try to solve the naming conflict and it will return a = 1.

I was also confused about this until i read this post on "JavaScript Hoisting" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Hope it helps.

查看更多
登录 后发表回答