今天给大家分享一篇文章,原文地址: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 ,所以发生了类型错误。