我正在学习一些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
函数是异步的吗?当它附加事件时,事件的值会发生变化吗?
答案 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的函数范围产生词法范围。
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;
尝试点击它,ev
为keyup
并查看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);
}
&#13;
<button id="btn">Click Me!</button>
<span id="result"></span>
&#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,它以某种方式保留了对(这是一个闭包)的引用,并找到分配给它的最后一个值。