Пример закрытия JavaScript и цепочки областей действия
-
21-12-2019 - |
Вопрос
Может ли кто-нибудь объяснить мне (ясно и кратко), почему этот код работает именно так?Я имею опыт строго типизированной работы с Java (6 и 7), где замыкания не существуют и не работают так, как в JavaScript.Я думаю, что концепции, связанные с этим вопросом, следующие:замыкания и цепочка областей видимости.
Вот пример:
var myfuncs = function() {
var funcs = []
var i;
for (i = 0; i < 10; i++) {
funcs[i] = function() { console.log(i); }
}
return funcs;
}
var allfuncs = myfuncs();
allfuncs.forEach(function(fn) { fn(); });
В приведенном выше примере регистрируется 9 (10 раз), но мои ожидания и моя собственная интуиция предполагали, что будет зарегистрировано 0–9.
Почему это работает так, как в Javascript?Замыкания — это очень мощное средство, но я пытаюсь усвоить эту концепцию раз и навсегда!Слегка измененный пример дает правильный результат, но почему?
var myfuncs = function() {
var funcs = []
var i;
for (i = 0; i < 10; i++) {
funcs[i] = (function(index) { console.log(index); })(i);
}
return funcs;
}
var allfuncs = myfuncs();
allfuncs.forEach(function(fn) { fn(); });
Замыкания не являются уникальными для Javascript, но я хочу понять, почему они эффективны в контексте того, когда JavaScript фактически написан для взаимодействия с браузером/домом.
Есть ли у кого-нибудь хорошие практические примеры того, как мы можем применять технику закрытия при взаимодействии с браузером/домом?
Спасибо.
Решение
В приведенных вами примерах это очень просто.
В вашем первом примере есть только одна переменная i
и все ссылается на это единственное значение.Так..он печатает номер 9
десять раз.Каждая функция захватывает общий значение i
это меняется.
Во втором примере вы используете замыкание.Каждая функция имеет частную переменную, называемую index
который получает - и это важная часть - копировать стоимости i
.
Итак, вы получаете 0
через 9
потому что есть десять функций, каждая из которых имеет приватный index
переменная и каждая из них index
переменные получают снимок i
как оно существовало в то время.
Эта более длинная форма закрытия может помочь:
function myFactory(index) {
return function() {
console.log(index);
}
}
var myfuncs = function() {
var funcs = []
var i;
for (i = 0; i < 10; i++) {
funcs[i] = myFactory(i);
}
return funcs;
}
var allfuncs = myfuncs();
allfuncs.forEach(function(fn) { fn(); });