Как работает внутреннее свойство [[scope]]?

Здравствуйте! Изучаю замыкания и натолкнулся на следующий момент. Имеется пример!

function outer (){
let counter = 0;
  function incrementCounter (){
    counter ++;
  }
return incrementCounter;
}
let myNewFunction = outer();
myNewFunction();
myNewFunction();
var anotherFunction = outer(); // myNewFunction = incrementCounter
anotherFunction();
anotherFunction();

Результат вызова myNewFunction() равен 1. Следующий 2…
Не совсем понятно, почему результат функции anotherFunction() имеет другую ссылку на внешний объект.

Вот как я это понимаю.
При определении функции incrementCounter(как и любой другой, в том числе и внешней, глобальной функции), javascript интерпретатор создаёт специальный внутренний объект [[scope]], который содержит все переменные этой функции, в том числе и ссылку на окружение, в котором создавалась данная функция(кстати, и здесь у меня сейчас появился вопрос… что такое scope? Ведь у нас есть локальная память функции, в которой сохраняются переменные. В Scope храниться только ссылка на внешнее окружение и на переменную counter, в нашем случае…??? То есть, при определении функции, создаётся локальная память и Scope?) … Далее, сохраняя функцию outer в переменную myNewFunction, мы сохраняем в том числе и scope, то есть ссылку на внешнее окружение. Но почему тогда, одна и та же ссылка не сохраняется в разные переменные? Мы не можем сохранить значение counter, которое после двух вызовов myNewFunction равняется 2 и продолжить увеличивать в 3 и 4. Очень прошу объяснить этот момент! И поправьте пожалуйста меня там, где я ошибся!

Как эта механика лежит у меня в голове:

Представь что при вызовеouter код выполняется последовательно, выражение за выражением. Выходит создается переменная counter, создается функция incrementCounter. И созданный incrementCounter возвращается из функции. По механике работы интерпретатора - где и как бы не вызывалась incrementCounter, ей всегда доступны переменные из того места где она была создана. Это место называют scope.

А myNewFunction и anotherFunction разные потому что это 2 разных объекта которые создались в двух вызовах outer.


Я не думаю что scope работает так же как и свойства js. Это внутреннее свойство интерпретатора и может содержать в себе что угодно, хоть айдишник на часть структуры что хранит в себе ссылки на значения из подобласти видимости.

Так можно сказать.

Скорее функция из myNewFunction видит тот скоуп в котором была создана.

При каждом вызове outer создается новый скоуп и новая incrementCounter, и новый counter.

Что будет при таком вызове, скажи пожалуйста?

myNewFunction();
myNewFunction();

Вызов outer так же создал область видимости в которой создалась функция incrementCounter и coutner. myNewFunction ссылается на функцию что создана и возвращена из outer. Вызов myNewFunction изенит значение переменной counter в той области видмости в которой myNewFunction была объявлена. В итоге значение counter будет 2. Это можно проверить, добавив console.log после инкремента в вызове incrementCounter

А что здесь происходит? Почему у нас не продолжается увеличение счётчика?

var anotherFunction = outer(); // myNewFunction = incrementCounter
anotherFunction();
anotherFunction();

Тут вызов outer создал новый скоуп, новый counter и новую incrementCounter.Ссылка на incrementCounter записана в anotherFunction. А дальше 1 в 1 как в сообщении выше.

только потому что это другая переменная, anotherFunction ? Но функция этого не видит:

function outer (){
let counter = 0;
  function incrementCounter (){
    counter ++;
  }
return incrementCounter;
}

И функция другая и переменная другая

1 лайк

Так, это же такая же функция, как и здесь:
let myNewFunction = outer();

Почему ты думаешь что она та же?

этот вызов:

myNewFunction();
myNewFunction();

позволяет так думать. В первом 1, во втором 2. И так и должно было продолжаться, в сторону увеличения!

Что противоречит тому что myNewFunction и anotherFunction - разные функции?

но они же содержат одну и ту же функцию, вот в чём дело

Ты выше рассказал почему это так.

Значит myNewFunction и anotherFunction - разные функции. Значит должно быть что этому противоречит. В этом коде или в принципе.

Всё, я понял! Здесь:
let myNewFunction = outer();
мы вызываем outer и сохраняем функцию incrementCounter в myNewFunction и повторно вызываем внутреннюю функцию. А ниже:
var anotherFunction = outer();
мы вызываем внешнюю функцию с новой переменной counter, которая равна 0

1 лайк

Тоже самое происходит и c var anotherFunction = outer();.


Давай чуть иначе глянем на вопрос.

function getArr() {
	return []
}

var arr1 = getArr()
var arr2 = getArr()

console.log(arr1 === arr2)

что выведет console.log?