thisKey.addEventListener(
'mousedown',
(function(_temp) {
return function() {
fnPlayKeyboard({
keyCode: _temp
});
}
})(reverseLookup[n + ',' + i])
);
看到这行代码,我对 addEventListener 的第二个参数中的函数如何工作感到困惑。我知道总体目标是在单击键盘上的按键时播放正确的声音。
在其余代码中,fnPlayKeyboard 接受事件 e 作为参数,并根据 e.keyCode 播放音符。 verseLookup 应该查找给定音符的 keyCode,此处用 n+','+i 表示。
我猜测代码以某种方式将 mousedown 事件转换为 keydown 事件,但不确定它是如何做到这一点的。让我特别困惑的是语法,因为似乎有一个 double ()() 作为 addEventListener 的第二个参数。
最佳答案
这是一个立即调用并返回另一个函数的函数。然后返回的函数被指定为 mousedown 监听器。
由于尝试创建函数范围变量 _temp
来摆脱闭包内循环问题,因此可能会非常复杂。如果ES2015允许,那就清楚多了。该代码相当于:
// ES2015
const keyCode = reverseLookup[n + ',' + i];
thisKey.addEventListener('mousedown', () => {
fnPlayKeyboard({ keyCode });
});
它采用 n
和 i
变量,无论它们是什么,并在 reverseLookup
(可能是一个对象)上查找它们,以获取keyCode
。然后,当 thisKey
收到 mousedown
事件时,它会使用具有该 keyCode
的对象调用 fnPlayKeyboard
。
代码不一定等同于
// Pre-ES2015
var keyCode = reverseLookup[n + ',' + i];
thisKey.addEventListener('mousedown', function() {
fnPlayKeyboard({ keyCode: keyCode });
});
因为,如果代码位于循环内,则 keyCode
只会有一个绑定(bind)(这将是在循环的最终迭代中分配给它的最终值):
// Pre-ES2015
for (var i = 0; i < 10; i++) {
var keyCode = reverseLookup[n + ',' + i];
thisKey.addEventListener('mousedown', function() {
fnPlayKeyboard({ keyCode: keyCode });
});
}
上面的代码不会按预期工作,但仅在 ES2015+ 环境中允许通过使用 const
声明变量来修复它。在较旧的环境中,立即在 addEventListener
中调用匿名 (function(_temp) { return function() {
是确保监听器拥有正确 >keyCode
调用时,通过仅为此监听器创建函数范围变量(_temp
参数)。
关于javascript - 如何使用闭包在循环内设置事件监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60142224/