我正在使用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。
有关如何实现这一目标的任何想法?谢谢!
答案 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。