Повторное использование той же функции shortcut.js для обработки ввода с клавиатуры
Я использую 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;
});
В идеале я могу обобщить функцию так, чтобы любой введенный ключ был фактически назначен переменной points, за исключением случая, когда пользователь вводит 0. В этом случае переменная points устанавливается в -1.
Есть идеи, как это сделать? Спасибо!
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'.
Я надеюсь, что это правильно отвечает на ваши вопросы, не стесняйтесь оставлять дальнейшие комментарии, если это не так. Для получения дополнительной информации о замыканиях см. Закрытия в MDN.