http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
这是我读过的关于托管的最好的文章。
声明、名称和吊装
在 JavaScript 中,名称以四种基本方式之一进入范围:
语言定义:默认情况下,所有作用域都被赋予名称 this 和 arguments。形参:函数可以具有命名形参,其作用域为该函数的主体。函数声明:这些是函数 foo() {} 的形式。变量声明:它们采用 var foo; 的形式。函数声明和变量声明总是被 JavaScript 解释器以不可见的方式移动(“提升”)到其包含范围的顶部。显然,函数参数和语言定义的名称已经存在。这意味着这样的代码:
function foo() {
bar();
var x = 1;
}
实际上是这样解释的:
function foo() {
var x;
bar();
x = 1;
}
事实证明,包含声明的行是否会被执行并不重要。以下两个函数是等价的:
function foo() {
if (false) {
var x = 1;
}
return;
var y = 1;
}
function foo() {
var x, y;
if (false) {
x = 1;
}
return;
y = 1;
}
请注意,声明的赋值部分没有被提升。只有名字被吊起。这不是函数声明的情况,整个函数体也将被提升。但请记住,声明函数有两种常规方式。考虑以下 JavaScript:
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
在这种情况下,只有函数声明的主体被提升到顶部。名称 'foo' 被提升,但主体被留下,在执行期间被分配。
这涵盖了提升的基础知识,这并不像看起来那么复杂或令人困惑。当然,这是 JavaScript,在某些特殊情况下会稍微复杂一些。