Javascript 为什么阴影变量在范围外定义时计算为未定义?
考虑以下代码:Javascript 为什么阴影变量在范围外定义时计算为未定义?,javascript,variables,shadowing,Javascript,Variables,Shadowing,考虑以下代码: <html><head></head> <body> <script type="text/javascript"> var outside_scope = "outside scope"; function f1() { alert(outside_scope) ; } f1(); </script> &
<html><head></head>
<body>
<script type="text/javascript">
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
}
f1();
</script>
</body>
</html>
var outside_scope=“outside scope”;
函数f1(){
警报(超出范围);
}
f1();
此代码的输出是警报框显示消息“outside”(外部
范围”。但是,如果我稍微将代码修改为:
<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>
var outside_scope=“outside scope”;
函数f1(){
警报(超出范围);
var out_scope=“inside scope”;
}
f1();
警报框显示消息“未定义”。我本来可以的
如果在两种情况下都显示“未定义”,则理解逻辑。但是,
这是不可能的。它仅在第二种情况下显示“未定义”。为什么会这样
提前感谢您的帮助 在第一种情况下,您的代码正在访问全局变量“outside_scope”,该变量已初始化为“outside scope”
Javascript具有函数级作用域,因此在第二种情况下,它正在访问函数作用域变量“outside_scope”,但在出现警报框时它尚未初始化。因此它显示未定义。在第二个示例中,局部变量存在于整个函数范围内。在警报之后定义它并不重要,它存在于整个函数中
然而,实际的赋值直到警报之后才发生,因此“未定义”。这是一个有趣的例子 在第一个示例中,您定义了一个“全局”变量。它具有全局作用域,因此可以在执行的任何函数/对象中访问 在第二个示例中,您使用函数范围变量“阻止”了全局变量,但由于在发出警报时它尚未初始化,因此返回“未定义”
我同意这不是最直观的怪癖,但它确实有意义。JavaScript有函数作用域,而不是块作用域 在第二种情况下,extern_scope的声明被提升到函数的顶部(但赋值不是) 这是一个很好的例子,说明了如果将所有变量声明放在函数顶部,JavaScript代码更容易阅读的原因。您的第二个示例相当于:
function f1() {
var outside_scope;
alert(outside_scope);
outside_scope = "inside scope";
}
现在,您可能理解了为什么会出现“未定义”的情况。变量受约束。这意味着,无论变量放置在函数中的什么位置,它都会移动到定义它的范围的顶部 例如:
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所具有的函数唯一作用域,建议在声明时声明所有变量,以类似将发生的情况。这是由于一种称为提升变量声明的方法 基本上,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()
。我为此写了一篇深入的博客文章。我希望这能帮助您理解代码中发生了什么
这也是原因,建议在JavaScript中在函数顶部声明变量。它可以帮助您理解代码在运行时的作用。多年后,我不知道这一点,可能是因为我总是在顶部声明,就像在C中一样。