Может ли кто-нибудь объяснить объяснение области видимости переменной в JS, поскольку оно применяется к объектам, функциям и закрытию?
OO Javascript: окончательное объяснение области переменных
Ответ 1
Глобальные переменные
Каждая переменная в Javascript является именованным атрибутом объекта. Например: -
var x = 1;
x добавляется к глобальному объекту. Глобальный объект предоставляется контекстом script и может уже иметь набор атрибутов. Например, в браузере глобальный объект - это окно. Эквивалентом указанной выше строки в браузере будет: -
window.x = 1;
Локальные переменные
Теперь, если мы изменим это на: -
function fn()
{
var x = 1;
}
При вызове fn
создается новый объект, называемый контекстом выполнения, также называемым областью (я использую эти термины взаимозаменяемо). x
добавляется как атрибут этого объекта области видимости. Следовательно, каждый вызов fn
получит свой собственный экземпляр объекта области видимости и, следовательно, его собственный экземпляр атрибута x, прикрепленного к этому объекту области видимости.
Закрытие
Теперь давайте рассмотрим следующее: -
function fnSequence()
{
var x = 1;
return function() { return x++; }
}
var fn1 = fnSequence();
var fn2 = fnSequence();
WScript.Echo(fn1())
WScript.Echo(fn2())
WScript.Echo(fn1())
WScript.Echo(fn2())
WScript.Echo(fn1())
WScript.Echo(fn1())
WScript.Echo(fn2())
WScript.Echo(fn2())
Примечание. Замените WScript.Echo
тем, что записывается в stdout в вашем контексте.
Последовательность, которую вы должны получить: -
1 1 2 2 3 4 3 4
Итак, что здесь произошло? У нас есть fnSequence
, который инициализирует переменную x
до 1 и возвращает анонимную функцию, которая вернет значение x
, а затем увеличит его.
Когда эта функция сначала выполняется, создается объект области видимости, и к этому объекту области видимости добавляется атрибут x
со значением 1. Также создается в одном и том же объекте выполнения анонимная функция. Каждый объект функции будет иметь атрибут scope, который указывает на контекст выполнения, в котором он создан. Это создает то, что известно как цепочка областей, к которой мы придем позже. Ссылка на эту функцию возвращается fnSequence
и сохраняется в fn1
.
Обратите внимание, что fn1
теперь указывает на анонимную функцию и что анонимная функция имеет атрибут scope, указывающий на объект области, в котором все еще есть атрибут x
. Это называется closure
, где содержимое контекста выполнения по-прежнему доступно после того, как функция, для которой она была создана, завершила выполнение.
Теперь эта же последовательность происходит при назначении fn2
. fn2
будет указывать на другую анонимную функцию, созданную в другом контексте выполнения, который был создан, когда fnSequence
был вызван этим вторым временем.
Цепочка областей
Что произойдет, если функция, выполняемая fn1
, выполняется в первый раз? Для выполнения анонимной функции создается новый контекст выполнения. Возвращаемое значение можно найти из идентификатора x
. Объект области функции проверяется для атрибута x
, но ни один не найден. Здесь происходит цепочка областей действия. Не удалось найти x
в текущем контексте выполнения. JavaScript принимает объект, удерживаемый атрибутом области функции, и ищет там x
. Он находит это, поскольку область функций была создана внутри выполнения fnSequence
, извлекает ее значение и увеличивает его. Следовательно, 1 выводится, а x
в этой области увеличивается до 2.
Теперь, когда выполняется fn2
, он в конечном итоге привязан к другому контексту выполнения, атрибут x
все еще равен 1. Следовательно, выполнение fn2
также приводит к 1.
Как вы можете видеть, fn1
и fn2
генерируют собственную независимую последовательность чисел.
Ответ 2
Переменные, не объявленные с помощью var, являются глобальными по объему. Функции вводят область действия, но обратите внимание, что если блоки и другие блоки не вводят область действия.
Я также мог увидеть много информации об этом с помощью области JavaScript в Google. Это действительно то, что я бы рекомендовал. http://www.digital-web.com/articles/scope_in_javascript/
Ответ 3
Функции вводят область. Вы можете объявлять функции внутри других функций, тем самым создавая вложенную область. Внутренняя область видимости может иметь доступ к внешнему пространству, но внешний не может получить доступ к внутренней области.
Переменные привязаны к области, используя ключевое слово var. Все переменные неявно связаны с областью верхнего уровня. Поэтому, если вы опускаете ключевое слово var, вы неявно ссылаетесь на переменную, связанную с верхним уровнем. В браузере верхний уровень - это окно. Обратите внимание, что окно - это переменная, поэтому окно == window.window