Замыкание. В учебнике не разбирают один момент.
Здравствуйте. Объясните пожалуйста, почему в теме про замыкание не объясняется то, что функция присваивается переменной?
https://learn.javascript.ru/article/...ecounter-2.svg Почему я при таком вызове makeCounter()() (без переменной) не получаю нужного результата? Каким образом в таком случае я постоянно получаю единицу, а с переменной результат сохраняется и выводит его корректный? Где-то читал, что создается образец функции, но как он создается по какому правилу? |
Каждый новый вызов функции makeCounter() делает следующее:
1) создаёт локальную переменную count и присваивает ей значение 0. 2) возвращает функцию, которой доступна только что созданная переменная count. Т.о., если вы несколько раз вызовете makeCounter() и сохраните её результат в разных переменных, то вы получите несколько независимых счётчиков: let counter1 = makeCounter(); let counter2 = makeCounter(); А если вы не сохранили результат действия ф-ии makeCounter() в переменной, то соответствующий контекст сразу же теряется. Именно это и происходит при немедленном вызове makeCounter()() (следующий такой же вызов делает всё заново, т.е. значение счётчика count снова будет равно нулю). |
Хм.. А каким образом сохраняется контекст в переменную?
Как происходит запоминание увеличенного значения? Разве это не одно и тоже: makeCounter()(); let counter = makeCounter(); counter() Мы же для переменно присвоили ссылку на функцию, только внутреннюю. И когда вызываем counter(), то происходит по сути одно и тоже, если бы мы вызывали makeCounter()() - counter()(). В чем тут может быть отличие? |
Devero97,
Для каждой функции в джаваскрипте доступны все её собственные переменные, а также переменные всех функций в которые она вложена. А вот переменные соседних функций ей недоступны. Ф-я, которую возвращает makeCounter(), вложена в этот самый makeCounter(), поэтому ей доступны её переменные (count). Но при этом переменная count не является частью возвращаемой ф-ии, поэтому её значение сохраняется между вызовами этой вложенной ф-ии (если результат makeCounter() сохранить в переменную, а потом вызвать несколько раз). Другая фишка джаваскрипта заключается в том, что каждый вызов любой ф-ии создаёт все её внутренние объекты (локальные переменные и функции) заново. Т.е. каждый вызов makeCounter() создаст новый экземпляр переменной count и вернёт новую функцию: function makeCounter(){ let count = 0; return function(){ console.log(count++); } } let counter1 = makeCounter(); let counter2 = makeCounter(); console.log("Трижды вызываем counter1():"); counter1(); counter1(); counter1(); console.log("Дважды вызываем counter2():"); counter2(); counter2(); Если вы вызываете внутреннюю функцию сразу - makeCounter()(); то вы не можете вызвать тот же самый объект второй раз, поскольку не сохранили ссылку на него. И следующий вызов makeCounter()(); сначала вернёт новый объект, а затем вызовет его как функцию. Т.е. такие вызовы будут всегда возвращать ноль. |
Цитата:
function makeCounter2(){ let count = 0; function plus(){ console.log(count++); } plus(); plus(); plus(); } makeCounter2(); Так понятней как происходит запоминание увеличенного значения? Замыкание делает абсолютно то же самое, только ссылка на внутреннюю функцию plus() попадает за пределы ф-ии makeCounter2() и может вызываться оттуда. Но новый вызов makeCounter2() выведет три числа опять с нуля, т.к. первой строкой создаётся новая переменная count со значением ноль. Конструкция makeCounter()() работает ровно так же. |
Цитата:
Вот тут и происходит недопонимание. Даже в том примере, который вы переписали, где происходит вызов функции plus() внутри функции makeCounter(). Функция plus() после вызова перезаписывает значение переменной или она только запоминает как-то у себя это значение? Я понимаю, что она по лексическому окружению не видит локальной переменной и по ссылке идет в другое лексическое окружение, и при обнаружении нужной переменной она ее берет и изменяет в другом лексическом окружении или она эту переменную как-то изменяет у себя в лексическом окружении? |
Devero97,
makeCounter() -- это новая функция,копия с образца и count новый, и эта новая функция будет менять только "свой" count. |
рони,
На какой вопрос вы даете ответ? |
Цитата:
|
рони,
Каким образом это происходит? Как функция plus() при вызове сохраняет в себе измененное значение и последующем вызове plus() это значение снова изменяется? Про то, как при повторном вызове makeCounter2() переменная заново инициализируется я понял, мне бы понять каким образом в функции plus() сохраняется эта переменная. |
Часовой пояс GMT +3, время: 11:21. |