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>
正在尝试解释:
尝试点击它,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);
}
<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 个值。
第二个 event
id 在包含它的匿名函数 执行 时计算,即当事件触发时。在那一刻,JS 引擎返回到 event
var,它以某种方式保留了对它的引用(这是一个闭包),并找到分配给它的最后一个值。
我正在学习一些 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>
正在尝试解释:
尝试点击它,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);
}
<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 个值。
第二个 event
id 在包含它的匿名函数 执行 时计算,即当事件触发时。在那一刻,JS 引擎返回到 event
var,它以某种方式保留了对它的引用(这是一个闭包),并找到分配给它的最后一个值。