Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > JavaScript, Ajax
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.06.2016, 00:33   #1
MrQuestion
Пользователь
 
Регистрация: 16.08.2015
Сообщений: 40
По умолчанию [[Scope]],LE и замыкания в JS

Код:
function makeCounter() {
  var currentCount = 1;
  
  return function() { 
   return currentCount++;
  };
}



var counter = makeCounter(); 
alert(counter()) ; 
alert(counter()) ; 
alert(counter()) ;
Здравствуйте.
Возникла небольшая проблема с логикой действий. Алерты поочередно показывают 1,2,3.
И если первый Алерт, показывающий единицу мне понятен, то второй и третий так работать не должны.
Значит, логика такая.
1)Первый counter получает ссылку на currentCount внешней функции, видит, что currentCount присвоена единица и забирает эту единицу себе и так как инкремент находится в постфиксной форме, Алерт выводит на экран не двойку, а единицу.

2)Второй counter получает ссылку на currentCount, видит, LE currentCount == 1 и забирает эту единицу себе. По идее второй Алерт тоже должен выдать единицу, ибо во внешнем LE currentCount == 1.

Я так понимаю между 1 и 2 пунктом происходит некая перезапись currentCount в внешнем LE.

Вопрос такой: Как эта перезапись происходит и перезапись ли это вообще?
MrQuestion вне форума Ответить с цитированием
Старый 18.06.2016, 01:39   #2
Naive
Раздолбайских Дел
Старожил
 
Аватар для Naive
 
Регистрация: 22.05.2009
Сообщений: 3,828
По умолчанию

не знаю, что такое LE, может я не очень программер... но тут у тебя makeCounter — это функция со своей областью видимости, currentCount в ней создается при вызове и возвращается функция, которая будет юзать то внутреннее поле...

Код:
var counter = makeCounter();
вот тут создается замыкание, в переменную counter приходит безымянная функция, которую ретурнит makeCounter, внутри которой она можеть сколь угодно насиловать свои внутренние переменные, currentCount, в данном случае.

Можешь сделать
Код:
var counter2 = makeCounter();
и он будет работать независимо от первого. В этом смысл замыкания, это инкапсуляция.
Alar, верни репу!
Naive вне форума Ответить с цитированием
Старый 18.06.2016, 11:05   #3
MrQuestion
Пользователь
 
Регистрация: 16.08.2015
Сообщений: 40
По умолчанию

Спасибо. Я понимаю, как происходит замыкание, и что происходит при присвоении var counter = makeCounter();

Не понятно, как counter может изменять переменную не своего внутреннего поля, а внешнего поля makeCounter().
Т.е. currentCount при каждом вызове counter() так и должна оставаться единицей. Почему она перезаписывается с каждым вызовом counter()?
MrQuestion вне форума Ответить с цитированием
Старый 18.06.2016, 11:38   #4
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Потому что замыкания так работают, а не так как вы придумали.

Что такое LE?
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 18.06.2016, 11:46   #5
MrQuestion
Пользователь
 
Регистрация: 16.08.2015
Сообщений: 40
По умолчанию

LE - Lexical Environment, термин из учебника. Объект функции, который включает в себя все внутренние переменные функции и [[Scope]]
MrQuestion вне форума Ответить с цитированием
Старый 18.06.2016, 11:48   #6
MrQuestion
Пользователь
 
Регистрация: 16.08.2015
Сообщений: 40
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Потому что замыкания так работают, а не так как вы придумали.
Это, конечно, хорошо, что они работают. Другое дело в том, что не понимая механики этой работы, как , вообще, можно их использовать?..
MrQuestion вне форума Ответить с цитированием
Старый 18.06.2016, 12:45   #7
Naive
Раздолбайских Дел
Старожил
 
Аватар для Naive
 
Регистрация: 22.05.2009
Сообщений: 3,828
По умолчанию

Цитата:
Сообщение от MrQuestion Посмотреть сообщение
Это, конечно, хорошо, что они работают. Другое дело в том, что не понимая механики этой работы, как , вообще, можно их использовать?..
Не понимаешь — не используй. Я понимаю — я использую.
Все просто.
Alar, верни репу!
Naive вне форума Ответить с цитированием
Старый 18.06.2016, 14:15   #8
MrQuestion
Пользователь
 
Регистрация: 16.08.2015
Сообщений: 40
По умолчанию

Цитата:
Сообщение от Naive Посмотреть сообщение
Не понимаешь — не используй. Я понимаю — я использую.
Все просто.
Я задал вопрос на этом форуме для того, чтобы понять.
Я задал вопрос, чтобы получить на него ответ, а не пинок под зад.
MrQuestion вне форума Ответить с цитированием
Старый 18.06.2016, 14:19   #9
Вадим Мошев

Старожил
 
Аватар для Вадим Мошев
 
Регистрация: 12.11.2010
Сообщений: 8,568
По умолчанию

Коротко смысл замыканий можно объяснить так.

Каждая вложенная функция видит переменные своих объемлющих функций (если эти вложенные функции не перекрывают их путём объявления их инструкцией var), то есть область видимости (scope) распространяется вглубь по функциям.

Это значит, что переменная mySuperVar, объявленная во внешней программе, вне всяких функций будет видна:
1. внутри функции f, которая объявлена внутри основной программы;
2. Внутри функции g, объявленной внутри функции f, которая объявлена во внешней программы;
3. Внутри функции h, которая объявлена внутри функции g, которая объявлена внутри функции f, которая объявлена в основной программе...
И так далее.

Теоретически это так, хотя не стоит использовать глобальные переменные внутри функций, это плохой подход.

Если, допустим, мы внутри функции f объявили ЛОКАЛЬНУЮ переменную innerVariable, то такая переменная будет видна внутри функций f (что очевидно), g и h, но не во внешней программе.
Вадим Мошев вне форума Ответить с цитированием
Старый 18.06.2016, 14:27   #10
MrQuestion
Пользователь
 
Регистрация: 16.08.2015
Сообщений: 40
По умолчанию

Черт. Все же просто. Внутренняя функция изменяет переменные внешней функции точно так же, как внешняя изменила бы обычную глобальную переменную. По тому же принципу. Все ясно. Черт. Это был действительно тупой вопрос. Спасибо
MrQuestion вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
адаптер замыкания на себя kral123 Свободное общение 2 15.02.2013 16:46
Замыкания и setTimeout Виталий Желтяков JavaScript, Ajax 7 26.01.2012 13:16
abc was not declared in this scope Farrel Qt и кроссплатформенное программирование С/С++ 2 21.04.2011 17:56
error: was not declared in this scope Serjuk Помощь студентам 2 29.03.2011 15:59
Замыкания Viconte JavaScript, Ajax 1 07.11.2010 21:08