带注释的来源;我假设这段代码从全局范围开始:
var local = true; // Creates a global variable called `local`
function outer() {
/* local scope */
var local = false; // Creates a local `local` within `outer`, shadowing (hiding) the global
function inner() {
alert(local); // alerts "undefined", the value of `inner`'s `local`
var local; // Creates a local `local` within `inner`, shadowing (hiding) `outer`'s version
}
inner();
}
outer();
function a(x) { // Creates a global function `a`
return x * 2;
}
var a; // Has no effect
alert(a); // alerts the function source (on engines that have it)
上面的代码中基本上有三件事在起作用:
嵌套范围内的声明会隐藏(隐藏)包含范围内的声明。所以local
in outer
shadows the global 和local
in inner
shadows outer
's local
。
var
声明在执行进入执行上下文时被处理,而不是它们出现在源代码中的位置。它们有时被称为“提升”,因为它们被有效地向上移动(提升、提升)到它们发生的上下文的顶部。(更多:糟糕的误解var
)这种效果在函数中特别明显inner
,因为local
被警告的是 from inner
,而不是 from outer
(这就是它的原因undefined
),即使声明位于警报下方。
函数声明在定义它们的范围内创建一个符号,在与var
声明相同的符号空间中。(具体来说,它们都在它们发生的执行上下文的词法环境的绑定对象中创建条目。)因此,如果您有一个函数声明和具有相同名称的 a (就像您在代码末尾所做的那样) ,有冲突。哪个赢?函数声明获胜,因为规范 §10.5规定的顺序,它说函数声明发生在声明之前,并且已经定义的符号的 a 不会覆盖它。var
a
var
var