Чтобы понять это поведение, вам необходимо понять, что такое закрытие. Короткий (но, вероятно, запутанным, если вы на самом деле не в ладу с закрытием) ответ:
Каждый вызов s1
выполняет следующие действия:
A) Создайте переменную с именем счетчика и инициализировать его в 0
Это кажется достаточно простым ...
B) Создайте функцию, которая увеличивает переменную из (а), и установить переменную addCount
, чтобы указать на него
Некоторые важные детали здесь скрыты. Переменная, которую эта функция будет обновлять, равна той, которая была создана на этапе (A) , тем же вызовом из s1
. Это следствие механизма закрытия.
Конечно, когда второй вызов s1
достигает этот шаг, он переписывает значение addEvent
, заменив функцию, который увеличивает на count
созданного предыдущего вызова s1
с новой функцией, которая увеличивает значение count
, созданные этот текущим вызов от s1
.
С) Создает и возвращает функцию, которая записывает значение переменной, созданной в (А)
Как и (B), то эта функция тоже видит переменную, созданную стадии А, текущего вызова от s1
.
Так что это значит?
Ну, вы называете s1
один раз, и это создает переменную со значением 0, и возвращает функцию, которая регистрирует эту переменную (функции, которую припасли в result1
).
В качестве побочного эффекта этот вызов установил addCount
функции, которая изменила бы значение переменной, зарегистрированной на result1
, если вы ее вызвали ... но вы ее не называете.
Вместо этого вы вызываете s1
, который заменяет addCount
новой функцией, которая обновляет новую переменную (также инициализируется до 0). Он возвращает функцию, которая регистрирует эту новую переменную, которую вы храните как result2
.
Теперь вы делаете вызов через addCount
, который вызывает функцию второго обновляет вторую переменной . Затем вы вызываете result1
, регистрируя первую переменную (которая никогда не обновлялась), а затем вы вызываете result2
, регистрируя вторую переменную (которую вы увеличили один раз).
После каждого вызова s1, addCount ссылается на переменную count, на которую ссылается замыкание, созданное этим вызовом. Таким образом, addCount() при вызове ссылается на переменную count в замыкании, на которую ссылается result2 – antlersoft
Это обсуждается в ответах, но я хочу обратить внимание на ваше внимание (Rodney_Dian): ответ, который вы приняли, неверен и будет путать ваше понимание дальше. Вы можете доказать, что это неправильно, добавив больше вызовов в 'result1()' и 'result2()' в конце вашего кода. Вы обнаружите, что независимо от того, сколько раз или в каком порядке вы их называете, каждый вызов 'result1()' возвращает 0, и каждый вызов 'result2()' возвращает 1. (Если вы не вызываете 'addCount()' снова , что приведет к дальнейшему увеличению 'result2()', оставив 'result1()' все еще на 0.) Прочтите другие ответы ниже, чтобы понять, почему. –