考虑以下代码:
<html><head></head>
<body>
<script type="text/javascript">
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
}
f1();
</script>
</body>
</html>
此代码的输出是警告框显示“外部”消息 范围“。但是,如果我稍微修改代码为:
<html><head></head>
<body>
<script type="text/javascript">
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
var outside_scope = "inside scope";
}
f1();
</script>
</body>
</html>
警告框显示消息“ undefined ”。我本可以有 如果在两种情况下都显示“未定义”,则理解逻辑。但是,那 没有发生。它仅在第二种情况下显示“未定义”。这是为什么?
提前感谢您的帮助!
答案 0 :(得分:20)
变量受提升的约束。这意味着无论变量放在函数中的哪个位置,它都会移动到定义它的作用域的顶部。
例如:
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
var outside_scope = "inside scope";
}
f1();
获取解释为:
var outside_scope = "outside scope";
function f1() {
var outside_scope; // is undefined
alert(outside_scope) ;
outside_scope = "inside scope";
}
f1();
因此,以及JavaScript所具有的仅功能范围,建议在top of the function声明所有变量,使其类似于将要发生的事情。
答案 1 :(得分:12)
在第一种情况下,您的代码正在访问全局变量“outside_scope”,该变量已初始化为“外部范围”。
Javascript具有功能级别范围,因此在第二种情况下,它正在访问函数范围变量“outside_scope”,但在警报框时尚未初始化。所以它显示未定义。
答案 2 :(得分:5)
JavaScript具有功能范围,而不是块范围。
在第二种情况下,outer_scope的声明被提升到函数的顶部(但是赋值不是)。
这是一个很好的例子,说明如果将所有变量声明放在函数顶部,JavaScript代码更容易阅读。你的第二个例子相当于:
function f1() {
var outside_scope;
alert(outside_scope);
outside_scope = "inside scope";
}
你现在可以理解为什么你会“未定义”。
答案 3 :(得分:4)
在第二个示例中,整个函数范围存在局部变量。在警报之后定义它并不重要,整个函数存在。
但是,直到警报之后才会发生实际分配,因此“未定义”。
答案 4 :(得分:1)
这是一个有趣的案例。
在第一个示例中,您已定义了一个“全局”变量。它具有全局范围,因此可以在任何函数/对象中访问以执行。在第二个示例中,您已使用函数范围变量“阻止”全局变量,但由于它在警报时尚未初始化,因此返回“未定义”。
我同意这不是最直观的怪癖,但它确实有意义。
答案 5 :(得分:1)
这是由于提升变量声明。
基本上,JavaScript 将变量声明分成两个,将分配保留在声明处并将实际声明提升到函数顶部:
var f1 = function () {
// some code
var counter = 0;
// some more code
}
var f2 = function () {
var counter; // initialized with undefined
// some code
counter = 0;
// some more code
}
在运行时,f1()
会被转换为f2()
。我写了一篇关于这个here的深度博客文章。我希望这有助于您了解代码中发生的情况。
这也是原因,建议在JavaScript中的函数顶部声明变量。它可以帮助您了解代码运行时的功能。