我正在使用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 的情况下。在这种情况下,会设置点变量到-1。
关于如何实现这一点有什么想法吗?谢谢!
最佳答案
带有闭包的循环应该可以解决问题:
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 .
关于javascript - 重用相同的shortcut.js函数来处理键盘输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11207829/