Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 03.08.2019, 19:51
Интересующийся
Отправить личное сообщение для Devero97 Посмотреть профиль Найти все сообщения от Devero97
 
Регистрация: 03.08.2019
Сообщений: 17

Замыкание. В учебнике не разбирают один момент.
Здравствуйте. Объясните пожалуйста, почему в теме про замыкание не объясняется то, что функция присваивается переменной?
https://learn.javascript.ru/article/...ecounter-2.svg

Почему я при таком вызове makeCounter()() (без переменной) не получаю нужного результата?

Каким образом в таком случае я постоянно получаю единицу, а с переменной результат сохраняется и выводит его корректный?

Где-то читал, что создается образец функции, но как он создается по какому правилу?
Ответить с цитированием
  #2 (permalink)  
Старый 03.08.2019, 21:06
Аватар для Белый шум
Профессор
Отправить личное сообщение для Белый шум Посмотреть профиль Найти все сообщения от Белый шум
 
Регистрация: 19.01.2012
Сообщений: 505

Каждый новый вызов функции makeCounter() делает следующее:
1) создаёт локальную переменную count и присваивает ей значение 0.
2) возвращает функцию, которой доступна только что созданная переменная count.

Т.о., если вы несколько раз вызовете makeCounter() и сохраните её результат в разных переменных, то вы получите несколько независимых счётчиков:
let counter1 = makeCounter();
let counter2 = makeCounter();

А если вы не сохранили результат действия ф-ии makeCounter() в переменной, то соответствующий контекст сразу же теряется. Именно это и происходит при немедленном вызове makeCounter()() (следующий такой же вызов делает всё заново, т.е. значение счётчика count снова будет равно нулю).
Ответить с цитированием
  #3 (permalink)  
Старый 03.08.2019, 21:30
Интересующийся
Отправить личное сообщение для Devero97 Посмотреть профиль Найти все сообщения от Devero97
 
Регистрация: 03.08.2019
Сообщений: 17

Хм.. А каким образом сохраняется контекст в переменную?

Как происходит запоминание увеличенного значения?

Разве это не одно и тоже:
makeCounter()();
 let counter = makeCounter();
 counter()


Мы же для переменно присвоили ссылку на функцию, только внутреннюю. И когда вызываем counter(), то происходит по сути одно и тоже, если бы мы вызывали makeCounter()() - counter()().

В чем тут может быть отличие?
Ответить с цитированием
  #4 (permalink)  
Старый 04.08.2019, 05:25
Аватар для Белый шум
Профессор
Отправить личное сообщение для Белый шум Посмотреть профиль Найти все сообщения от Белый шум
 
Регистрация: 19.01.2012
Сообщений: 505

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()(); сначала вернёт новый объект, а затем вызовет его как функцию. Т.е. такие вызовы будут всегда возвращать ноль.
Ответить с цитированием
  #5 (permalink)  
Старый 04.08.2019, 05:42
Аватар для Белый шум
Профессор
Отправить личное сообщение для Белый шум Посмотреть профиль Найти все сообщения от Белый шум
 
Регистрация: 19.01.2012
Сообщений: 505

Сообщение от Devero97 Посмотреть сообщение
Хм.. А каким образом сохраняется контекст в переменную?

Как происходит запоминание увеличенного значения?
Давайте немного перепишем пример:
function makeCounter2(){
 let count = 0;
 function plus(){
  console.log(count++);
 }
 plus();
 plus();
 plus();
}

makeCounter2();

Так понятней как происходит запоминание увеличенного значения?

Замыкание делает абсолютно то же самое, только ссылка на внутреннюю функцию plus() попадает за пределы ф-ии makeCounter2() и может вызываться оттуда.

Но новый вызов makeCounter2() выведет три числа опять с нуля, т.к. первой строкой создаётся новая переменная count со значением ноль. Конструкция makeCounter()() работает ровно так же.
Ответить с цитированием
  #6 (permalink)  
Старый 04.08.2019, 11:46
Интересующийся
Отправить личное сообщение для Devero97 Посмотреть профиль Найти все сообщения от Devero97
 
Регистрация: 03.08.2019
Сообщений: 17

Сообщение от Белый шум Посмотреть сообщение
Давайте немного перепишем пример:
function makeCounter2(){
 let count = 0;
 function plus(){
  console.log(count++);
 }
 plus();
 plus();
 plus();
}

makeCounter2();

Так понятней как происходит запоминание увеличенного значения?

Замыкание делает абсолютно то же самое, только ссылка на внутреннюю функцию plus() попадает за пределы ф-ии makeCounter2() и может вызываться оттуда.

Но новый вызов makeCounter2() выведет три числа опять с нуля, т.к. первой строкой создаётся новая переменная count со значением ноль. Конструкция makeCounter()() работает ровно так же.

Вот тут и происходит недопонимание. Даже в том примере, который вы переписали, где происходит вызов функции plus() внутри функции makeCounter(). Функция plus() после вызова перезаписывает значение переменной или она только запоминает как-то у себя это значение?

Я понимаю, что она по лексическому окружению не видит локальной переменной и по ссылке идет в другое лексическое окружение, и при обнаружении нужной переменной она ее берет и изменяет в другом лексическом окружении или она эту переменную как-то изменяет у себя в лексическом окружении?
Ответить с цитированием
  #7 (permalink)  
Старый 04.08.2019, 12:47
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,105

Devero97,
makeCounter() -- это новая функция,копия с образца и count новый, и эта новая функция будет менять только "свой" count.
Ответить с цитированием
  #8 (permalink)  
Старый 04.08.2019, 12:59
Интересующийся
Отправить личное сообщение для Devero97 Посмотреть профиль Найти все сообщения от Devero97
 
Регистрация: 03.08.2019
Сообщений: 17

рони,
На какой вопрос вы даете ответ?
Ответить с цитированием
  #9 (permalink)  
Старый 04.08.2019, 13:06
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,105

Сообщение от Devero97
она эту переменную как-то изменяет у себя в лексическом окружении?
да
Ответить с цитированием
  #10 (permalink)  
Старый 04.08.2019, 13:12
Интересующийся
Отправить личное сообщение для Devero97 Посмотреть профиль Найти все сообщения от Devero97
 
Регистрация: 03.08.2019
Сообщений: 17

рони,
Каким образом это происходит?
Как функция plus() при вызове сохраняет в себе измененное значение и последующем вызове plus() это значение снова изменяется?

Про то, как при повторном вызове makeCounter2() переменная заново инициализируется я понял, мне бы понять каким образом в функции plus() сохраняется эта переменная.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Jquery touch events все срабатывает в один момент falkone Events/DOM/Window 6 01.09.2015 15:36