重用相同的shortcut.js函数来处理键盘输入

时间:2012-06-26 12:59:11

标签: javascript keyboard-shortcuts keyboard-events

我正在使用shortcut.js处理键盘输入,我想知道是否有更有效的方法来实现我的目标(目前大多数相同的代码都被复制和粘贴)。

例如,我有:

  shortcut.add("0",function() {
    points = -1;
    sec = 0;
  }); 

  shortcut.add("1",function() {
    points = 1;
    sec = 0;
  }); 

  shortcut.add("2",function() {
    points = 2;
    sec = 0;
  }); 

  shortcut.add("3",function() {
    points = 3;
    sec = 0;
  }); 

理想情况下,我可以推广该函数,以便在用户输入0的情况下,输入的任何键都实际分配给points变量之外。在这种情况下,设置points变量到-1。

有关如何实现这一目标的任何想法?谢谢!

1 个答案:

答案 0 :(得分:3)

带闭包的循环应该可以解决问题:

for (var i = 0; i <= 9; ++i) {
    (function(i) {  // Capture current value of 'i' in this scope.
        shortcut.add(i.toString(), function() {
            points = i || -1;  // 'i' if 'i' is not 0, else -1.
            sec = 0;
        });
    })(i);
}

更新以下评论:那么为什么我们需要在这里关闭?最终的(i);是什么意思?

基本上,我们需要一个闭包,因为传递给shortcut.add()的匿名函数不会立即被调用,而是在循环终止后的某个时间。这些函数通过引用而非值来捕获i,这意味着它们会在运行时看到i当前的值,而不是他们被定义的时间

所以,如果我们直接从循环体中调用shortcut.add(),我们传递的所有匿名函数最终都会看到循环终止后当前的i值,这将永远是相同(10)。

在每次迭代中创建一个新变量看起来可行,但不会:

for (var i = 0; i <= 9; ++i) {
    var _i = i;  // Create new variable containing current value of 'i'.
    shortcut.add(i.toString(), function() {
        points = _i || -1;  // Won't work, '_i' is always 9.
        sec = 0;
    });
}

由于for循环体在Javascript中没有自己的范围,_i最终在函数范围内,与i相同,并且将以相同的方式捕获(最终值为9而不是10,因为++i不适用于此。)

所以,我们真正需要的是每次迭代中的新范围。为了实现这一点,我们可以在循环内定义一个函数,并立即调用它,并将当前值传递给i

var newScope = function(i) {
    // Here, the value of 'i' will be the one current when 'newScope' is called
    // and will not change, even if 'i' is captured by other functions.
};
newScope(i);  // Call function with current value of 'i'.

最后,我们可以在不引入newScope名称的情况下直接将调用运算符()应用于函数定义:

(function(i) {
    // Here, the value of 'i' will be the one current when this function is
    // called and will not change, even if 'i' is captured by other functions.
})(i);  // Call function with current value of 'i'.

我希望这能恰当地回答你的问题,如果没有,请随时留下进一步的评论。有关闭包的更多信息,请参阅Closures on MDN