【问题标题】:How to set an event listener inside a loop using closures如何使用闭包在循环内设置事件侦听器
【发布时间】:2020-02-10 07:37:52
【问题描述】:
thisKey.addEventListener(
  'mousedown',
  (function(_temp) {
    return function() {
      fnPlayKeyboard({
        keyCode: _temp
      });
    }
  })(reverseLookup[n + ',' + i])
);

看到这行代码,我很困惑 addEventListener 的第二个参数中的函数是如何工作的。我知道总体目标是在单击键盘上的某个键时播放正确的声音。

在其余代码中,fnPlayKeyboard 将事件 e 作为参数,并根据 e.keyCode 播放音符。 reverseLookup 应该查找一个给定音符的 keyCode,这里用 n+','+i 表示。

我猜代码是以某种方式将 mousedown 事件转换为 keydown 事件,但不确定它是如何做到的。令我特别困惑的是语法,因为似乎有一个 double ()() 作为 addEventListener 的第二个参数。

【问题讨论】:

    标签: javascript closures dom-events


    【解决方案1】:

    这是一个立即调用并返回另一个函数的函数。然后将返回的函数分配为 mousedown 侦听器。

    可能很复杂,因为它试图创建一个函数范围的变量_temp 以摆脱闭包内循环问题。如果允许 ES2015,那就清楚多了。代码相当于:

    // ES2015
    const keyCode = reverseLookup[n + ',' + i];
    thisKey.addEventListener('mousedown', () => {
      fnPlayKeyboard({ keyCode });
    });
    

    它获取ni 变量,无论它们是什么,并在reverseLookup(可能是一个对象)上查找它们以获得keyCode。然后,当thisKey 接收到mousedown 事件时,它会调用fnPlayKeyboard,并使用具有该keyCode 的对象。

    代码不一定等价于

    // Pre-ES2015
    var keyCode = reverseLookup[n + ',' + i];
    thisKey.addEventListener('mousedown', function() {
      fnPlayKeyboard({ keyCode: keyCode });
    });
    

    因为,如果代码在循环中,则keyCode 将只有一个绑定(这将是在循环的最终迭代中分配给它的最终值):

    // Pre-ES2015
    for (var i = 0; i < 10; i++) {
      var keyCode = reverseLookup[n + ',' + i];
      thisKey.addEventListener('mousedown', function() {
        fnPlayKeyboard({ keyCode: keyCode });
      });
    }
    

    上面的代码不会像预期的那样工作,但是通过使用const 声明变量来修复它只允许在 ES2015+ 环境中。在较旧的环境中,立即在 addEventListener 中调用匿名 (function(_temp) { return function() { 是确保侦听器在调用时具有正确的 keyCode 的一种方法,方法是创建一个函数范围的变量(_temp 参数),仅用于这个监听器。

    【讨论】:

    • 感谢您的澄清。你能解释一下 double (...)(...) 是什么意思吗:(function(_temp)...)(reverseLookup[...]) reverseLookup 是如何传递给 function(_temp) 的?
    • 这是一个返回函数的函数。 (reverseLookup[n + ',' + i]) 是参数列表。当解释器遇到addEventListener 行时,它会评估要传递给内部函数(function(_temp) { return function() { fnPlayKeyboard({keyCode:_temp}); } })的参数。它为(reverseLookup[n + ',' + i]) 提供了一个东西,然后将它传递给函数,并将那个“东西”作为_temp 参数。
    猜你喜欢
    • 2016-03-29
    • 1970-01-01
    • 2016-03-01
    • 2014-04-21
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多