#javascript #closures #counter #iife
#javascript #замыкания #счетчик #iife
Вопрос:
На www.w3schools.com/js/js_function_closures.asp существует базовый пример счетчика в закрытии, и, насколько я могу судить, IIFE:
var add = (function () {
var counter = 0;
console.log(counter);
return function () {return counter = 1;}
})();
add();
add();
add();
// the counter is now 3
Однако, после нескольких часов чтения области видимости, замыканий и IIFES, не в первый раз, и просмотра других простых примеров, я все еще не понимаю, почему var counter = 0;
строка выполняется только один раз. Журнал консоли, который я добавил сразу после этой строки, никогда ничего не выводит, как будто он никогда не вызывается.
Почему счетчик не сбрасывается на 0 при каждом вызове add() ? Какие концепции я неправильно понимаю? Спасибо за вашу помощь.
Комментарии:
1. Функция вызывается немедленно, поэтому
counter
инициализация происходит только один раз. Теперьadd
это возвращаемая функция, которая просто увеличиваетсяcounter
.2.
var add
не ссылается на внешнюю функцию, которая идет после=
; он ссылается на ту, которая возвращаетсяreturn function() { ... }
, так что это та, которую вы вызываете, когда делаетеadd()
.3.
console.log
Строка выводится0
для меня перед первымadd()
вызовом?4. @Bergi это потому, что это IIFE, вызываемый во время инициализации — иначе перед первым add();
5. @rabbitco Да, точно, но OP утверждает, что » эта строка никогда ничего не выводит »
Ответ №1:
Я все еще не понимаю, почему строка var counter = 0; выполняется только один раз.
Потому что функция IIFE вызывается только один раз. add()
Вызовы выполняют эту функцию:
function () {return counter = 1;}
который возвращается из IIFE. Вы можете проверить это, указав имена функций и проверив имя выполняемой функции:
var add = (function iife() {
var counter = 0;
console.log(counter);
return function inner() {return counter = 1;}
})();
add.name; // `inner`, not `iife`
Журнал консоли, который я добавил сразу после этой строки, никогда ничего не выводит,
как будто он никогда не вызывается
Этого не может быть. Он должен выводиться 0
только один раз.
Ответ №2:
Первым шагом для механизма Javascript (после объявления add
) является инициализация add
, что приводит к вызову IIFE, что снова приводит к:
var add = function () {
return counter = counter
}
потому что IIFE возвращает эту функцию как значение, которому нужно присвоить add
. Функция, назначенная для add
, по-прежнему имеет доступ к лексической области видимости IIFE ( var counter
): это закрытие.
Каждый add()
из них является вызовом функции, возвращаемой из IIFE, и поэтому var counter = 0
вызывается только один раз (во время инициализации add
).