Счетчик JavaScript с закрытием и IIFE

#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 ).