Javascript范围变量理论

时间:2010-12-10 04:48:20

标签: javascript html scope

我有两个表现不同的示例页面,我想知道原因。对我来说,他们似乎基于我收集的关于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>&nbsp;</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中没有区别时。

3 个答案:

答案 0 :(得分:8)

在执行任何代码之前,

varfunction声明悬挂

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中被提升 - 即该函数在顶部运行,您尝试访问的变量未定义。