理解javascript中变量和函数的挂起 hoisting

今天给大家分享一篇文章,原文地址:http://jamesallardice.com/explaining-function-and-variable-hoisting-in-javascript/

 

 javascript的域机制(scoping mechanism)是这门语言最难懂的地方之一,如果你不能完全理解他,你就会遇到很多困难。而理解域机制的钥匙就是理解挂起概念 ( the concept of hoisting)

 

直接看下面的例子:

var x = 10;
function y() {
    console.log(x); //Prints undefined
    var x = 20;
    console.log(x); //Prints 20
}
y();
console.log(x); //Prints 10

如果你理解最基本的域机制,你应该清楚,function y 可以访问到第一行声明的x  根据这个逻辑,由于我们给x赋值10,所以很容易想到第一个console.log 的结果应该是10 而不是undefined

 

这是由于function y中的第二行影响了结果,如果你去掉第二行(var x=20)  第一个console.log 的结果就是10了。 那么这是为什么呢???这叫要说到javascript中的挂起hoisting , 上面的例子其实可以这么理解:

 

var x; //x声明被挂起 (x is undefined)
x = 10; //赋值 (x is 10)
function y() {
    var x; //声明另一个也叫x的变量,被挂起(x is undefined)
    console.log(x); //打印 undefined
    x = 20; //赋值(x is 20)
    console.log(x); //打印 20
}
y();
console.log(x); //变量x在外边的域还是10

这个简单的例子可以充分证明挂起的概念在变量定义中的作用,有2点要记住:

 

首先,我们在第一个例子中看到的奇怪现象是因为恰好有个同名的变量x  ,   第二个x的调用发生在赋值之前了。

 

其次,声明本身被挂起了,而赋值会在我们写下的同时发生作用。

 

同理,function的声明也会被挂起在他被定义的那个域中。 

 

 sayHello(); //调用发生在声明之前
function sayHello() {
    console.log("Hi!");
}

根据挂起理论:由于函数声明被域挂起了,所以在他之前的调用是有效的。

 

再看一个函数表达式的例子

 

sayHello(); // TypeError, undefined is not a function!
var sayHello = function() {
    console.log("Hi!");
};

由于函数表达式是一个变量声明和赋值操作,所以变量被挂起了,但由于赋值发生在调用之后。

调用sayHello()时候该变量sayHello还不是一个function   ,所以发生了类型错误。

 

 

 

 

 

 

posted @ 2013-12-20 11:36  叫什么都行  阅读(1469)  评论(0编辑  收藏  举报