javascript hoisting var vs let

时间:2016-01-01 08:53:44

标签: javascript ecmascript-6 ecmascript-5 hoisting

我正在学习一些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 eventfor循环之外被提升但是为什么每次迭代循环都会在数组中得到最后一个事件('keyup')?
addEventListener函数是异步的吗?当它附加事件时,事件的值会发生变化吗?

2 个答案:

答案 0 :(得分:2)

在您的示例中,所有事件都已注册,但内部event变量和外部event变量不同,因为没有块级别范围和功能级别范围。

这4个事件&#39;点击&#39;&#39; dblclick&#39;,&#39; keydown&#39;,&#39; keyup&#39;已注册,但最后的事件值为keyup,因此'event: ' + event;始终为event: keyup

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

&#13;
&#13;
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);
}
&#13;
<button id="btn">Click Me!</button>
<span id="result"></span>
&#13;
&#13;
&#13;

试图解释:

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

&#13;
&#13;
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);
}
&#13;
<button id="btn">Click Me!</button>
<span id="result"></span>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

确实有某种东西&#34;异步&#34; (有点)发生,因为两个event次出现不会同时评估。

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

第一个event会立即在循环中进行评估,因此请获取4个值。

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