Javascript函数作用域[Javascript Essentials]

Javascript function scope [Javascript Essentials]

本文关键字:Javascript Essentials 作用域 函数      更新时间:2023-09-26

我正在看Travis Tidwell的Javascript Essentials,他在那里解释了这段代码:

(function() {
    var messages = ['hello', 'there'];
    for (var i in messages) {
        setTimeout(function() {
            console.log(messages[i]);
        }, 10); 
    };
})();

它在控制台上重复了两次'there',但我仍然不明白为什么。谁能一步一步地跟我讲讲这段javascript ?

每次代码在循环中运行时,它都会设置一个事件处理程序,以便在10ms后,它记录messages[i]的值。

在这些超时时间的10ms过去之前,i的值已经被(通过for循环)更改为1(因为这是数组中的最后一个属性名)。

第一次超时输出messages[1],第二次超时输出messages[1]


  1. 数组创建并存储在messages
  2. i设置为0并设置超时
  3. i设置为1并设置超时
  4. 第一个超时函数运行,i仍然是1
  5. 第二个超时函数运行,i仍然是1

JavaScript有函数作用域,而不像其他语言那样有块作用域。因此,实际上只存在一个i变量。当调用setTimeout中的代码时,i已经被设置为数组的最后一个索引。

很快,在ECMAScript 6中,我们可以用let声明块作用域变量。Mozilla Reference: let 在此之前,绕过此行为的一种方法是为需要独立于其他变量的变量创建一个新函数:

(function() {
  var messages = ['hello', 'there'];
  for (var i in messages) {
    (function(currentIndex) {
      setTimeout(function() {
        logToOutput(messages[currentIndex]);
      }, 10);
    })(i);
  };
})();
function logToOutput(msg) {
  document.getElementById("output").innerHTML += msg + "<br>";
}
<div id="output"></div>