Область действия — одно из наиболее важных понятий в JavaScript. Если вы хотите хорошо изучить JavaScript, вам необходимо понять, как работают область видимости и цепочки областей действия JavaScript. Сегодняшняя статья представляет собой краткое введение в область действия JavaScript и цепочку областей действия, в надежде помочь каждому лучше изучить JavaScript.
Область JavaScript
В любом языке программирования есть концепция области видимости. Проще говоря, область видимости — это доступный диапазон переменных и функций. То есть область видимости управляет видимостью и жизненным циклом переменных и функций. В JavaScript существует два типа области видимости переменных: глобальная и локальная.
1. Глобальный масштаб
Объекты, к которым можно получить доступ в любом месте кода, имеют глобальную область видимости. Вообще говоря, глобальную область действия имеют следующие ситуации:
(1) Самая внешняя функция и переменные, определенные вне самой внешней функции, имеют глобальную область видимости, например:
Скопируйте код кода следующим образом:
varauthorName="Горный ручей";
функцияdoSomething(){
варблогИмя="";
functioninnerSay(){
оповещение (имя блога);
}
внутреннийСай();
}
alert(authorName);//Горный ручей
alert(blogName);//Ошибка скрипта
сделать что-нибудь();//
InternalSay()//ошибка скрипта
(2) Все переменные, которые не определены и не назначены напрямую, автоматически объявляются имеющими глобальную область действия, например:
Скопируйте код кода следующим образом:
функцияdoSomething(){
varauthorName="Горный ручей";
имя_блога="";
оповещение (имя автора);
}
оповещение(имяблога);//
alert(authorName);//Ошибка скрипта
Переменная blogName имеет глобальную область действия, но доступ к AuthorName вне функции невозможен.
(3) Все свойства оконных объектов имеют глобальную область действия.
Обычно встроенные свойства объекта окна имеют глобальную область действия, например window.name, window.location, window.top и т. д.
2. Локальная область действия
В отличие от глобальной области, локальная область обычно доступна только в рамках фиксированного фрагмента кода, чаще всего внутри функции, поэтому в некоторых местах вы также увидите, что люди называют эту область областью функции, например, следующий код blogName и функция InsideSay имеют только локальную область действия.
Скопируйте код кода следующим образом:
функцияdoSomething(){
варблогИмя="";
functioninnerSay(){
оповещение (имя блога);
}
внутреннийСай();
}
alert(blogName);//Ошибка скрипта
innerSay();//ошибка скрипта
Цепь прицела
В JavaScript функции также являются объектами. Фактически, все в JavaScript является объектом. Объекты-функции, как и другие объекты, имеют свойства, к которым можно получить доступ через код, и набор внутренних свойств, доступных только движку JavaScript. Одним из внутренних свойств является [[Scope]], определенное третьей редакцией стандарта ECMA-262. Это внутреннее свойство содержит коллекцию объектов в области видимости, в которой создана функция. Эта коллекция называется цепочкой областей действия функции. , который определяет, к каким данным может обращаться функция.
Когда функция создается, ее цепочка областей заполняется объектами данных, доступными из области, в которой была создана функция. Например, определите следующую функцию:
Скопируйте код кода следующим образом:
функцияadd(num1,num2){
варсум=число1+номер2;
возвратная сумма;
}
Когда функция add будет создана, ее цепочка областей действия будет заполнена глобальным объектом, содержащим все глобальные переменные, как показано на следующем рисунке (примечание: на рисунке показана только часть всех переменных):
Область действия функции add будет использоваться во время выполнения. Например, выполните следующий код:
Скопируйте код кода следующим образом:
вар всего = добавить (5,10);
Когда эта функция выполняется, создается внутренний объект, называемый «контекстом выполнения». Контекст времени выполнения определяет среду, в которой выполняется функция. Каждый контекст времени выполнения имеет свою собственную цепочку областей действия для разрешения идентификаторов. При создании контекста времени выполнения его цепочка областей действия инициализируется объектом, содержащимся в [[Scope]] текущей выполняющейся функции.
Значения копируются в цепочку областей контекста времени выполнения в том порядке, в котором они появляются в функции. Вместе они образуют новый объект, называемый «объектом активации». Этот объект содержит все локальные переменные, именованные параметры, коллекции параметров и данные функции. Затем этот объект будет помещен в передний конец цепочки областей действия. уничтожается, активный объект также уничтожается. Новая цепочка областей показана ниже:
Если во время выполнения функции переменная не встречается, она проходит процесс разрешения идентификатора, чтобы определить, где получить и сохранить данные. Этот процесс начинается с головы цепочки областей, то есть с активного объекта, и ищет идентификатор с таким же именем. Если он найден, используйте переменную, соответствующую этому идентификатору. Если он не найден, продолжайте. поиск следующего объекта в цепочке областей Если Если после поиска объекты не найдены, идентификатор считается неопределенным. Во время выполнения функции каждый идентификатор подвергается такому процессу поиска.
Объединение областей действия и оптимизация кода
Из структуры цепочки областей видно, что чем глубже идентификатор расположен в цепочке областей контекста времени выполнения, тем медленнее будет скорость чтения и записи. Как показано на рисунке выше, поскольку глобальные переменные всегда существуют в конце цепочки области контекста среды выполнения, поиск глобальных переменных происходит медленнее всего во время разрешения идентификатора. Поэтому при написании кода следует как можно меньше использовать глобальные переменные и как можно больше использовать локальные. Хорошее практическое правило: если на объект перекрестной области ссылаются более одного раза, перед использованием сохраните его в локальной переменной. Например, следующий код:
Скопируйте код кода следующим образом:
функцияchangeColor(){
document.getElementById("btnChange").onclick=function(){
document.getElementById("targetCanvas").style.backgroundColor="red";
};
}
Эта функция дважды ссылается на документ глобальной переменной. Чтобы найти переменную, вы должны пройти всю цепочку областей, пока она наконец не будет найдена в глобальном объекте. Этот код можно переписать следующим образом:
Скопируйте код кода следующим образом:
функцияchangeColor(){
вардок = документ;
doc.getElementById("btnChange").onclick=function(){
doc.getElementById("targetCanvas").style.backgroundColor="red";
};
}
Этот код относительно прост и не даст значительного улучшения производительности после переписывания. Однако если в программе имеется большое количество глобальных переменных, к которым осуществляется постоянный доступ, производительность переписанного кода значительно повысится.
изменить цепочку областей действия
Соответствующий контекст времени выполнения уникален каждый раз при выполнении функции, поэтому многократный вызов одной и той же функции приведет к созданию нескольких контекстов времени выполнения. Когда функция завершит выполнение, контекст выполнения будет уничтожен. Каждый контекст времени выполнения связан с цепочкой областей действия. В обычных обстоятельствах во время выполнения контекста времени выполнения на его цепочку областей будут влиять только операторы with и catch.
Оператор with — это сокращенный способ использования объектов, позволяющий избежать написания повторяющегося кода. Например:
Скопируйте код кода следующим образом:
функцияinitUI(){
с (документ) {
варбд=тело,
ссылки = getElementsByTagName("a"),
я = 0,
лен=links.length;
в то время как (я <len) {
обновление (ссылки [я++]);
}
getElementById("btnInit").onclick=function(){
сделать что-нибудь();
};
}
}
Здесь используется оператор ширины, чтобы избежать многократной записи документа, что кажется более эффективным, но на самом деле вызывает проблемы с производительностью.
Когда код достигает оператора with, цепочка областей контекста времени выполнения временно изменяется. Создается новый изменяемый объект, содержащий все свойства объекта, указанного параметром. Этот объект будет помещен в начало цепочки областей видимости, а это означает, что все локальные переменные функции теперь находятся во втором объекте цепочки областей видимости и, следовательно, доступ к ним будет более дорогим. Как показано ниже:
Поэтому вам следует избегать использования оператора with в вашей программе. В этом примере простое сохранение документа в локальной переменной может повысить производительность.
Еще одна вещь, которая меняет цепочку областей действия, — это оператор catch в операторе try-catch. Когда в блоке кода try возникает ошибка, процесс выполнения переходит к оператору catch, а затем объект исключения помещается в изменяемый объект и помещается в начало области. Внутри блока catch все локальные переменные функции будут помещены во второй объект цепочки областей видимости. Пример кода:
Скопируйте код кода следующим образом:
пытаться{
сделать что-нибудь();
}поймать(бывший){
alert(ex.message);//Здесь меняется цепочка областей видимости
}
Обратите внимание, что после выполнения оператора catch цепочка областей действия вернется в предыдущее состояние. Оператор try-catch очень полезен при отладке кода и обработке исключений, поэтому не рекомендуется полностью его избегать. Вы можете снизить влияние операторов catch на производительность, оптимизировав свой код. Хороший шаблон — делегировать обработку ошибок функции, например:
Скопируйте код кода следующим образом:
пытаться{
сделать что-нибудь();
}поймать(бывший){
handleError(ex);//Делегируем метод процессора
}
В оптимизированном коде метод handleError — единственный код, выполняемый в предложении catch. Эта функция получает объект исключения в качестве параметра, что позволяет более гибко и единообразно обрабатывать ошибки. Поскольку выполняется только один оператор и доступ к локальным переменным не осуществляется, временные изменения в цепочке областей не повлияют на производительность кода.