【问题标题】:Confusion about scope and hoisting in Javascript关于 Javascript 中范围和提升的困惑
【发布时间】:2016-10-31 09:45:56
【问题描述】:
<!DOCTYPE>
<html>
<head>
    <link rel="stylesheet" href="styles.css"/>
    <body>
        <ul id="people-list"></ul>
        <script src="app.js"/>
    </body>
</head>
</html>

***app.js***

var people = ["alf","kay","jay","may"];
var list = document.getElementById("people-list");
for(var i =0; i< people.length; i++){
  var person = people[i];
  var element = document.createElement("li");
  (function (){
    var person = person;
    element.innerText = person;
    element.addEventListener("click",function(){
        alert("You clicked on "+ person);
    });
  }());
  list.appendChild(element);
}

为什么在全局作用域中创建的“person”变量没有在 IIFE 中被引用,因此会生成一个未定义列表,但变量名称从(例如 var person 到 var person2 以及随后的警报更改) ) 在 IIFE 中使代码正常工作。

【问题讨论】:

  • person不是在全局范围内创建的。创建没有vardefinition 的变量会将其提升到全局范围。否则它将在相应的范围内创建。
  • var person = person 毫无意义
  • 但是在IIFE之前,在全局范围内创建了一个person变量,对应people的各种索引。我说的对吗?
  • 只需评论var person = person; 并测试! var person 会将变量提升为 undefined,这就是 variable hoisting 的全部意义所在..

标签: javascript scope hoisting


【解决方案1】:

由于提升var person = person 完全等价于

var person;
person = person;

您不能在外部范围内引用person 变量。它完全被局部变量所掩盖,因此您将未定义的局部变量分配给它自己。

【讨论】:

    【解决方案2】:

    为什么在全局作用域中创建的“person”变量没有在 IIFE 中被引用

    因为您在 IIFE 范围内有一个 person 变量,它掩盖了它。

    如果你有两个同名的变量,在不同的作用域中,你只能访问在最近作用域中声明的那个。


    这里的提升没有影响,因为var person 出现在 IIFE 的第一行。

    如果它出现在 IIFE 中的任何其他行,那么它将被提升,相当于将它放在第一行。

    【讨论】:

      【解决方案3】:

      当您已经使用局部变量的名称时,您不能使用person 来引用外部循环变量,它是隐藏的。你可以传递一个参数

      var person = people[i];
      (function (person){
          …
      }(person));
      

      或者根本不使用外部作用域person

      (function (){
          var person = people[i];
          …
      }());
      

      【讨论】:

        【解决方案4】:

        通过var 声明变量将始终使用 JavaScript 的函数范围。为了在全局范围内声明变量,您只需保留 var 定义即可。

        var person = "your person" // function scope
        person = "your person" // global scope
        

        无论如何,您只是声明了同一个变量两次。这基本上意味着您正在覆盖您之前声明的person 的定义。这样做只会得到一个 undefined 变量,正如您在示例中看到的那样。

        【讨论】:

        • 关于您的第一点,我想推迟一下,我认为如果您在函数之外使用 var 关键字创建变量,它仍会在全局范围内注册。使用 var 关键字在浏览器控制台中输入一个变量,然后检查“window”,你会在那里找到它。
        猜你喜欢
        • 2022-01-14
        • 2012-04-09
        • 1970-01-01
        • 2017-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-05
        相关资源
        最近更新 更多