Javascript全局范围问题 - let和var

时间:2016-12-17 11:54:13

标签: javascript ecmascript-6

以下是我的HTML页面:

<html>

<head>
    <script type="text/javascript" src="/game/js/ready/main.js" ></script>
    <link rel="stylesheet" type="text/css" href="/game/css/nav.css" />
</head>

<body>

    <div class="nav-buttons">
        <span class="nav-button" onclick="f()">Show A</span>
        <span class="nav-button" onclick="h()">Show B</span>
        <span class="nav-button" onclick="g()">Show C</span>
    </div>

    <div id="divA">
    a
    </div>

    <div id="divB">
    b
    </div>

    <div id="divC">
    c
    </div>

</body>

</html>

以下是我的main.js文件:

var divA = document.getElementById("divA");
var divB = document.getElementById("divB");
var divC = document.getElementById("divC");

function f(){
    window.divA.style.display = "block";
    window.divB.style.display = "none";
    window.divC.style.display = "none";
}

function h(){
    window.divA.style.display = "none";
    window.divB.style.display = "block";
    window.divC.style.display = "none";
}

function g(){
    window.divA.style.display = "none";
    window.divB.style.display = "none";
    window.divC.style.display = "block";
}

据我所知,这是有效的。但是,当我调用f()时,我收到一条错误消息,指出所有上面定义的变量都是空的。

var关键字更改为let时,上述代码运行时没有任何问题。

这真的很奇怪,因为据我所知this answer,情况恰恰相反。

这是对我的误解,还是浏览器中的一个奇怪的错误?

3 个答案:

答案 0 :(得分:5)

您的var变量在全局范围内声明,可以作为全局属性进行访问。由于Why does jQuery or a DOM method such as getElementById not find the element?

,它们的值为空

使用let似乎有效,因为let变量不可用作全局对象的属性。所以你得到的不是你的变量,而是global polluter。全球污染者是一个肮脏的黑暗神奇的东西,它通过他们的ID使全局对象上的元素可用。它应该从未存在过。不要依赖它。这是不好的做法。

console.log(window.divA); // Horrendous !!!!
<div id="divA"></div>

答案 1 :(得分:2)

请注意,您收到的错误是未声明变量,但在您尝试访问时,他们所持有的值为null他们(当你致电f()时)。

这意味着在声明时,或者换句话说,当您从document.getElementById分配值时,没有包含ID divAdivB和{{的元素1}}。

&#13;
&#13;
divC
&#13;
var divA = document.getElementById("divA"); // null
var divB = document.getElementById("divB"); // null
var divC = document.getElementById("divC"); // null

function f(){
    window.divA.style.display = "block"; // error because window.divA is null
    window.divB.style.display = "none";  // error because window.divB is null
    window.divC.style.display = "none";  // error because window.divC is null
}

f();
&#13;
&#13;
&#13;

使用<!-- DOM IS EMPTY -->时的不同之处在于,变量不会被分配给let对象。他们的价值仍为window

&#13;
&#13;
null
&#13;
let divA = document.getElementById("divA"); // null
let divB = document.getElementById("divB"); // null
let divC = document.getElementById("divC"); // null

function f(){
    window.divA.style.display = "block"; // error because window.divA is undefined
    window.divB.style.display = "none";  // error because window.divB is undefined
    window.divC.style.display = "none";  // error because window.divC is undefined
}

f();
&#13;
&#13;
&#13;

请参阅Oriol's answer,了解<!-- DOM IS EMPTY -->似乎有效的原因

答案 2 :(得分:-1)

试试这个,你需要在页面加载完成后调用javascript,因为你需要使用onload方法。在加载之前如果你调用javascript divA,divB,divC给出null值。要避免这个空值,你需要在f()函数中使用它,并在使用onload方法加载页面后调用函数

&#13;
&#13;
<script>
  function f() {
    alert("function works");
    var divA = document.getElementById("divA");
    var divB = document.getElementById("divB");
    var divC = document.getElementById("divC");

    divA.style.display = "block";
    divB.style.display = "none";
    divC.style.display = "none";
  }
</script>

<body onload="f();">
  <div id="divA" style="width:100px;height:100px;background-color:Red;"></div>
  <div id="divB" style="width:100px;height:100px;background-color:green;"></div>
  <div id="divC" style="width:100px;height:100px;background-color:blue;"></div>
</body>
&#13;
&#13;
&#13;