javascript 提升 var vs let

javascript hoisting var vs let

我正在学习一些 ES6 功能,当然遇到了 let 关键字及其新范围(不同于 var) 我遇到了一个关于 var 及其提升的棘手范围的例子。 但我不能完全理解为什么我得到这个结果:

var events = ['click', 'dblclick', 'keydown', 'keyup'];

for (var i = 0; i < events.length; i++) {
  var event = events[i];
  document.getElementById('btn').addEventListener(event, function() {
    document.getElementById('result').innerHTML = 'event: ' + event;
  });
}
<button id="btn">Click Me!</button>
<span id="result"></span>

我知道 var event 是在 for 循环之外提升的,但为什么每次循环迭代都会在数组中获取最后一个事件 ('keyup')?
addEventListener 函数是异步的,并且在它附加事件时事件的值发生变化吗?

在您的示例中,所有事件都已注册,但内部 event 变量和外部 event 变量不同,因为没有块级作用域,只有函数级作用域。

这4个事件'click'、'dblclick'、'keydown'、'keyup'都被注册了,但是作为事件最后的值是因为keyup所以'event: ' + event; 将永远是 event: keyup.

您可以使用 IIFE ( immediately-invoked function expression ),这是一个 JavaScript 设计模式,它使用 JavaScript 的函数作用域产生词法作用域。

var events = ['click', 'dblclick', 'keydown', 'keyup'];

for (var i = 0; i < events.length; i++) {
  var event = events[i];
  (function(event) {
    document.getElementById('btn').addEventListener(event, function() {
      document.getElementById('result').innerHTML = 'event: ' + event;
    });
  })(event);
}
<button id="btn">Click Me!</button>
<span id="result"></span>

正在尝试解释:

尝试点击它,evkeyup 并查看 4 seconds 之后的行为。

var events = ['click', 'dblclick', 'keydown', 'keyup'];

for (var i = 0; i < events.length; i++) {
  var event = events[i];
  var ev = events[i];
  document.getElementById('btn').addEventListener(event, function() {
    document.getElementById('result').innerHTML = 'event: ' + ev;
  });
  
  setTimeout(function(){
    ev = "Look it is changed now, see the scoping!";
  },4000);
}
<button id="btn">Click Me!</button>
<span id="result"></span>

确实发生了 "asynchronous"(某种程度上)的事情,因为没有同时评估两个 event 事件。

document.getElementById('btn').addEventListener(event, function() {
    document.getElementById('result').innerHTML = 'event: ' + event;
  });

第一个 event 立即在循环中计算,因此获得 4 个值。

第二个 eventid 在包含它的匿名函数 执行 时计算,即当事件触发时。在那一刻,JS 引擎返回到 event var,它以某种方式保留了对它的引用(这是一个闭包),并找到分配给它的最后一个值。