我有两个表现不同的示例页面,我想知道原因。对我来说,他们似乎基于我收集的关于javascript中的作用域的一致性。
1.HTML:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function demofunction(x, y) {
z=x+y;
}
</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>4-6.htm</title>
</head>
<body>
<h1>Bad Scoping</h1>
<script type="text/javascript">
//<![CDATA[
demofunction(3, 2);
alert(z);
var z;
alert(z);
//]]>
</script>
<p> </p>
</body>
</html>
在此示例中,demofunction运行并将全局变量z设置为5. alert运行并且由于范围中没有z,它会抓取全局范围并找到等于5的z,它会发出警报。然后定义一个名为z的新局部变量。第二个警报可以看到该局部变量,但由于它未定义,它会选择全局变量并再次发出警报。
2.HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bad Scoping</title>
<script type="text/javascript">
//<![CDATA[
first = 6;
document.writeln('<p>first is ' + first + "</p>");
function letsSee() {
alert(first);
var first;
first = 4;
}
letsSee();
document.writeln('<p>but now first is ' + first + "</p>");
//]]>
</script>
</head>
<body>
</body>
</html>
全局优先设置为6. letsSee()运行并且警报(如果一致)应该看不到名为first的局部变量,因此它应该警告全局变量6.然后定义本地first,然后设置为4 .setsSee()存在,最后一个打印首先打印全局,再次显示6。
但是,这不会发生。会发生什么,它显示6,警报未定义,并显示6.我的问题是针对为什么它提醒undefined而不是6?如果我在letSee中对var first;
我的内容进行评论,那么我会看到它警告6然后显示为4.这对我来说很有意义。但为什么在警报之后首先使用var会对警报调用所看到的值产生影响?特别是当它在1.html中没有区别时。
答案 0 :(得分:8)
var
和function
声明悬挂。
function letsSee() {
alert(first);
var first;
first = 4;
}
表现得像
function letsSee() {
var first = undefined;
alert(first);
first = 4;
}
作为一个易于理解的示例,您可以在声明函数之前调用它们:
foo(); // works!
function foo() { ... }
这是因为function
声明首先被查看并被提升,您可以在任何地方调用它,无论您声明它的代码何时/何处。使用var
声明的变量也会发生同样的情况。变量本身(名称)被提升。在给定范围内的任何地方写<{1}} 将使该范围内的任何更高范围的变量var foo;
无法访问。
foo
答案 1 :(得分:3)
有两件事让你失望
1。您假设<script>...</script>
块具有自己的范围,就像函数具有范围一样。事实是所有<script>
块都存在于同一全局范围内。
2。您还假设var
声明按其在代码中出现的顺序发生。事实是,给定范围内的所有var
都在该范围的开头处执行。 (-edit-只是为了澄清:var 声明发生在作用域的开头,但是任何赋值操作都保留在代码中的原始位置。已声明的变量的值,但是尚未分配的值为undefined
)。
所以......在您的第一个示例中,var z
实际上是在全局范围内声明z
,然后对demofunction()
的调用就在全局范围内运行z
,并且两个警报都针对相同的全局z
运行。
然而,在您的第二个示例中,first
最初设置在全局范围内,然后在函数的 local 范围内再次声明。在该函数中,警报和赋值都在 local 变量上运行。在函数外部,writeln()
对全局变量进行操作。
答案 2 :(得分:0)
我认为这是因为函数声明在JavaScript中被提升 - 即该函数在顶部运行,您尝试访问的变量未定义。