OO Javascript: полное объяснение области видимости переменных - PullRequest
19 голосов
/ 19 сентября 2008

Может ли кто-нибудь дать объяснение области видимости переменных в JS применительно к объектам, функциям и замыканиям?

Ответы [ 3 ]

35 голосов
/ 19 сентября 2008

Глобальные переменные

Каждая переменная в Javascript является именованным атрибутом объекта. Например: -

var x = 1;

x добавлено к глобальному объекту. Глобальный объект предоставляется контекстом скрипта и может уже иметь набор атрибутов. Например, в браузере глобальным объектом является окно. Эквивалентом приведенной выше строки в браузере будет: -

window.x = 1;

Локальные переменные

А что если мы изменим это на: -

function fn()
{
    var x = 1;
}

Когда вызывается fn, создается новый объект, называемый контекстом выполнения , также называемый scope (я использую эти термины взаимозаменяемо). 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 тем, что пишет в стандартный вывод в вашем контексте.

Последовательность, которую вы должны получить: -

1 1 2 2 3 4 3 4

Так что здесь произошло? У нас есть fnSequence, который инициализирует переменную x в 1 и возвращает анонимную функцию, которая возвращает значение x и затем увеличивает его.

Когда эта функция выполняется впервые, создается объект области действия, и к этому объекту области действия добавляется атрибут x со значением 1. Также в этом же объекте выполнения создается анонимная функция. Каждый объект функции будет иметь атрибут области действия, который указывает на контекст выполнения, в котором он создан. Это создает так называемую цепочку областей действия , к которой мы придем позже. Ссылка на эту функцию возвращается fnSequence и сохраняется в fn1.

Обратите внимание, что fn1 теперь указывает на анонимную функцию и что анонимная функция имеет атрибут области действия, указывающий на объект области действия, к которому все еще прикреплен атрибут x. Это известно как closure, где содержимое контекста выполнения все еще доступно после завершения функции, для которой оно было создано.

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

Цепочка прицела

Что происходит, когда функция, удерживаемая fn1, выполняется в первый раз? Новый контекст выполнения создается для выполнения анонимной функции. Возвращаемое значение можно найти по идентификатору x. Объект области действия функции проверяется на наличие атрибута x, но ни один не найден. Вот тут и начинается цепочка областей действия . Не найдя x в текущем контексте выполнения, JavaScript берет объект, содержащийся в атрибуте области действия функции, и ищет там x. Он находит его, поскольку область функций была создана внутри выполнения fnSequence, извлекает его значение и увеличивает его. Следовательно, выводится 1, а x в этой области увеличивается до 2.

Теперь, когда fn2 выполняется, он в конечном итоге присоединяется к другому контексту выполнения, атрибут которого x по-прежнему равен 1. Следовательно, выполнение fn2 также приводит к 1.

Как видите, fn1 и fn2 каждый генерирует свою собственную независимую последовательность чисел.

4 голосов
/ 19 сентября 2008

Переменные, не объявленные с помощью var, имеют глобальный характер. Функции вводят область действия, но учтите, что если блоки и другие блоки не вводят область действия.

Я также мог видеть много информации об этом, используя поиск в Google Javascript. Это действительно то, что я бы порекомендовал. http://www.digital -web.com / статьи / scope_in_javascript /

1 голос
/ 19 сентября 2008

Функции вводят область действия. Вы можете объявлять функции внутри других функций, тем самым создавая вложенную область видимости. Внутренняя область видимости может получить доступ к внешней области видимости, но внешняя область не может получить доступ к внутренней области видимости.

Переменные привязываются к области, используя ключевое слово var . Все переменные неявно связаны с областью действия верхнего уровня. Поэтому, если вы опустите ключевое слово var, вы неявно ссылаетесь на переменную, привязанную к верхнему уровню. В браузере верхним уровнем является объект window . Обратите внимание, что window является переменной, поэтому window == window.window

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...