🐬 🐬 Комментарии и звезды приветствуются 🐳 🐳
Мы часто говорим,Все имеет свою ценность, это действительно хорошо, но подумайте, есть ли предпосылка,Все имеет некоторую ценность в некоторых областях более или менее.
Например,машина, безусловно, очень ценный материал, он очень удобен в наших повседневных поездках, перевозке грузов и т. д .;Палочки для еды, также очень ценный материал, он делает наши блюда очень удобными. но,машинаПоможешь нам донести еду до рта?Палочки для едыВы можете взять нас в путешествие?
Ну, что я сказал вышеопределенные поля, мы можем назвать этообъем, думаю можно.
Сказав это, я хочу спросить: в JSобъемЭто похожее понятие?
Прежде всего, я могу определенно сказать, что это очень важная концепция в JavaScript, и она связана со многими основными механизмами в JS.Понимая это, многие проблемы легко решаются.
Итак, спросите себя, что такое область видимости в JS?
Я, вероятно, знал, что это было в моем сердце, но, тщательно обдумав это, я, похоже, не смог ясно выразить это.
Не беда, давайте поближе познакомимся с этим интересным материалом.
Сначала бросьте концепцию:
Область отвечает за сбор и поддержку набора запросов, состоящего из всех объявленных идентификаторов (переменных), и за соблюдение очень строгого набора правил, определяющих права доступа к этим идентификаторам исполняемым в данный момент кодом.
С точки зрения непрофессионала, область действия эквивалентна администратору (с собственным набором правил), который отвечает за управление упорядоченным поиском всех объявленных идентификаторов.
Давайте расскажем историю о том, что на самом деле делают прицелы.
Три брата вместе
Давным-давно у меня было 3 хороших друга, старшего зовут движок, второго зовут редактор, а третьего зовут прицел. Трое братьев, казалось, старели, но у них все еще не было много денег на руках. Все торопились, поэтому трое братьев планировали что-то сделать вместе.
Процесс поиска работы: это примерно десятки тысяч слов. . .
В конце концов, они отвечают за компиляцию и запуск JS.
Их работа заключается в следующем:
Босс кидает им задание на компиляцию и выполнение следующего кода:
var a = 1;
console.log( a );
начинай работать:
- Компилятор: Scope, помогите мне посмотреть, сохранили ли вы переменную a.
- Объем: Второй брат, еще нет.
- Компилятор: Хорошо, оставьте один для меня.
- Двигатель: самый младший, который вы не назвали переменным.
- Компилятор: Старший брат, он действительно есть, второй брат просто попросил меня сохранить один.
- Двигатель: Отлично, помогите, какая у него стоимость, надо скопировать.
- Компилятор: Брат, его значение равно 2.
- Двигатель: Спасибо, третий брат, так что я могу напечатать его значение.
Вышеизложенное рассказывает неуместную маленькую историю, но отношения между этими тремя, вероятно, таковы.
Лексическая область видимости против динамической области видимости
- лексический объем
Тщательно понимать область действия JavaScriptКак упоминалось выше, первый этап работы большинства компиляторов стандартных языков называется лексикализация (также называемая лексикализация). Напомним, что процесс лексикализации проверяет символы в исходном коде и, в случае процесса синтаксического анализа с отслеживанием состояния, также присваивает семантику слов.
В JS используется область видимостилексический объем.
вообще говоря,Лексическая область - это область, определенная на лексической фазе.. другими словами,Лексическая область определяется тем, где вы пишете переменную и блочную область при написании кода., тем самым сохраняя область видимости неизменной, когда лексер обрабатывает код (что и происходит в большинстве случаев).
- динамическая область
В JS динамическая область действия тесно связана с этим механизмом.его область определяется во время выполнения
var a = 1;
function foo() {
var a = 2;
console.log( this.a );
}
foo(); // 1
Из приведенного выше кода видно, что значение печати a в foo не определяется тем, где написан код, а зависит от того, где выполняется foo.
-
разница
- Лексическая область определяется во время написания кода или определения, а динамическая область определяется во время выполнения. (тоже это!)
- Лексическая область видимости касается того, где объявлена функция, а динамическая область видимости касается того, откуда функция вызывается.
объем функции
В JS способ создания области видимости:
- функция
- with, eval (не рекомендуется, влияет на производительность)
Отсюда мы знаем, что в JSБольшинство спецификаций генерируются на основе функций.
Каждая функция создает для себя область видимости. Все идентификаторы в этом пузыре могут быть использованы в этом пузыре.
function bar() {
var a = 1;
function foo() {
var b = 2;
console.log(b);
}
foo();
console.log(a);
}
bar();
В приведенном выше коде столбец имеет идентификаторы a и foo, поэтому a и foo могут быть доступны в столбце; пузырь foo имеет идентификатор b, поэтому в столбце есть доступ к b; конечно, есть также глобальный пузырь, глобальный пузырь имеет идентификатор бара, поэтому бар доступен в глобальном пузырьке.
принцип наименьшего разрешения
Принцип наименьшей авторизации означает, что при проектировании программного обеспечения необходимый контент должен быть выставлен на минимум, а другой контент должен быть «спрятан», например, дизайн API модуля или объекта.
Этот принцип можно распространить на то, как выбирается область, содержащая переменные и функции. Если все переменные и функции находятся в глобальной области видимости, то, конечно, к ним можно получить доступ во всех внутренних вложенных областях. Но это нарушает упомянутый ранее принцип наименьших привилегий, потому что может открыться слишком много переменных или функций, которые должны быть закрытыми, и что правильный код должен иметь возможность предотвратить доступ к этим переменным или функциям.
Например:
function doSomething(a) {
b = a + doSomethingElse( a * 2 );
console.log( b * 3 );
}
function doSomethingElse(a) {
return a - 1;
}
var b;
doSomething( 2 ); // 15
В этом фрагменте кода переменная b и функция doSomethingElse(..) должны быть «закрытыми» для конкретной реализации внутри doSomething(..). Предоставление внешней области «доступа» к b и doSomethingElse(..) не только не нужно, но и может быть «опасно», так как они могут быть использованы неожиданным образом, намеренно или случайно, что приведет к тому, что что-то выйдет из-под контроля. ( ..) применяются условия. Более «разумный» дизайн скрыл бы эти частные особенности внутри doSomething(..) ,
Например:
function doSomething(a) {
function doSomethingElse(a) {
return a - 1;
}
var b;
b = a + doSomethingElse( a * 2 );
console.log( b * 3 );
}
doSomething( 2 ); // 15
Теперь ни b, ни doSomethingElse(..) не могут быть доступны извне, а только контролируются doSomething(..). Функциональность и окончательный эффект не затрагиваются, но конкретный контент приватизирован по дизайну, и соответствующим образом будет реализовано хорошо разработанное программное обеспечение.
избегать конфликта
Когда наш программный код постепенно увеличивается, неизбежно возникают конфликты переменных. Поэтому то, как избежать конфликта, становится особенно важным.
Функция может строго «скрывать» идентификатор, и к нему нельзя получить доступ извне, используя эту возможность, мы хорошо избегаем конфликтов.
function foo() {
var a = 1;
}
function bar() {
var a = 2;
}
FO и бар определяются в той же переменной A, но это не повлияет друг на друга. Поскольку функции могут быть очень хороши для идентификатора «скрыты».
- глобальное пространство имен
Классический пример конфликта переменных существует в глобальной области видимости. Когда в программу загружено несколько сторонних библиотек, легко могут возникнуть конфликты, если они не скрывают должным образом свои внутренние частные функции или переменные. Эти библиотеки обычно объявляют переменную с достаточно уникальным именем в глобальной области видимости, обычно это объект. Этот объект используется как пространство имен библиотеки, и все функции, которые должны быть представлены внешнему миру, станут свойствами этого объекта (пространства имен), а не будут раскрывать свои собственные идентификаторы в лексической области видимости верхнего уровня.
Например:
var myLibrary = {
name: 'echo',
getName: function() {
console.log( this.name );
}
}
Объявление функции и выражение функции
Основой для различия между объявлениями функций и функциональными выражениями является:Начинается ли жизнь функции с ключевого слова function.
Объявление, начинающееся с ключевого слова function, является объявлением функции, а все остальные объявления функций являются функциональными выражениями.
//函数声明
function foo() {
}
//函数表达式
var foo = function () {
};
(function() {
})();
Именованная функция против анонимной функции
-
именованная функция функция с именем
function foo() { } var foo = function bar() { } setTimeout( function foo() { } ) +function foo() { }();
требует внимания:Объявления функций должны называться функциями.
-
анонимная функция функция без имени
var foo = function () { } setTimeout( function foo() { } ) -function foo() { }();
Функция немедленного выполнения (IIFE)
vara=2;
(function foo() {
var a=3;
console.log( a ); // 3
})();
console.log( a ); // 2
Функция начинается с (), а не с ключевого слова function, поэтому IIFE — это функциональное выражение.
Имя функции, конечно, не требуется для IIFE, наиболее распространенным использованием IIFE является использование выражения анонимной функции. Хотя IIFE, использующие именованные функции, встречаются редко, они имеют следующие преимущества:
- Анонимные функции не отображают осмысленные имена функций в трассировках стека, что затрудняет отладку.
- Без имени функции можно использовать только ссылку arguments.callee с истекшим сроком действия, когда функция должна ссылаться на себя, например, в рекурсии. Другой пример, когда функция должна ссылаться на себя, — это когда прослушиватель событий должен отменить привязку после запуска события.
- Анонимные функции опускают имена функций, которые важны для удобочитаемости/понятности кода. Описательное имя делает код понятным.
Поэтому IIFE названных функций также является практикой, достойной продвижения.
- другая форма выражения
(function() {
}())
Это также выражение IIFE, которое функционально согласуется с описанным выше методом.Какой из них выбрать, зависит от личных предпочтений.
- Передача параметров
IIFE также может передавать параметры, как и другие формы функций (еще одно: передача параметров передается по значению).
(function foo(a) {
console.log(a);
})(3);
Другой вариант использования этого шаблона — разрешение (хотя и необычных) исключений, вызванных неправильным переопределением значения по умолчанию неопределенных идентификаторов. Назовите параметр undefined, но не передавайте какое-либо значение в соответствующей позиции, чтобы значение неопределенного идентификатора в блоке кода гарантированно было неопределенным:
undefined = true; // 给其他代码挖了一个大坑!绝对不要这样做!
(function IIFE( undefined ) {
var a;
if (a === undefined) {
console.log( "Undefined is safe here!" );
}
})();
- UMD (Universal Module Definition)
Другой вариант IIFE состоит в том, чтобы изменить порядок выполнения кода, поместив функцию, которую необходимо запустить, второй и передав ее в качестве параметра после выполнения IIFE. Хотя этот шаблон немного многословен, некоторым людям его легче понять.
var a=2;
(function IIFE( def ) {
//参数的处理
def( window );
})(function def( global ) {
//逻辑运算
var a=3;
console.log( a ); // 3
console.log( global.a ); // 2
});
область действия блока
В то время как область действия функции является наиболее распространенной единицей области видимости и, безусловно, наиболее распространенным подходом к проектированию в большей части JavaScript на сегодняшний день, существуют и другие типы единиц области видимости, и их даже можно поддерживать с помощью других типов единиц области видимости. Лучший, более чистый код.
- try...catch
Очень немногие заметят, что спецификация JavaScript ES3 предусматривает, что предложение catch в try/catch создает область действия блока, а переменная параметра catch действительна только внутри catch.
try{
throw undefined;
}catch(a){
a = 2;
console.log(a); // 2
}
console.log(a); // ReferenceError
- let
Стандарт ES6 позволяет нам легко создавать блочные области видимости, а одним из способов определения переменных является ключевое слово let.
Переменные, определенные с помощью let, имеют следующие характеристики:
- позволить невидимой области создания блока ({...})
- Переменные, объявленные с помощью let, не могут быть повышены, поэтому их можно только сначала определить, а затем использовать.
{
let a = 1;
console.log(a); // 1
}
console.log(a); // ReferenceError
Типичное применение let находится в цикле for
Давайте посмотрим на следующие два примера:
// 每秒输出一个5
for( var i = 0; i < 5 ; i++ ) {
setTimeout(() => {
console.log( i );
}, i *1000)
}
// 依次输出0,1,2,3,4,时间间隔位1秒
for( let i = 0; i < 5 ; i++ ) {
setTimeout(() => {
console.log( i );
}, i *1000)
}
Причина в том, что let формирует пять областей блока, так что каждая выходная переменная получается из области блока этого цикла.
Конечно, у нас могут быть и другие способы достижения второго эффекта, мыЗакрытие, это действительно красивосказал в.
- const
В дополнение к let в ES6 также введена константа, которую также можно использовать для создания переменных с блочной областью видимости, но значение которой является фиксированным (постоянным). Любая последующая попытка изменить значение приведет к ошибке.
var foo = true;
if (foo) {
var a=2;
const b = 3; // 包含在 if 中的块作用域常量
a=3;//正常!
b=4;//错误!
}
console.log( a ); // 3
console.log( b ); // ReferenceError!
цепочка прицелов
Цепочка областей состоит из текущей области и ряда родительских областей. Головной областью всегда является текущая область, а хвостом — глобальная область. Цепочка областей действия гарантирует упорядоченный доступ к переменным, к которым имеет доступ текущий контекст.
var a = 2;
function bar() {
function foo() {
console.log(a);
}
}
bar(); // 2
Приведенный выше код состоит из 3 слоев пузырьков области видимости.Пузырь foo пытается напечатать переменную a.Движок не находит переменную a в пузырьке foo, поэтому он переходит к родительской полосе области видимости, чтобы найти ее... и так далее, пока не найдет глобальную область видимости Bubble, найдет там переменную a и выведет ее значение. Если не найдено, сообщается ReferenceError.