Сначала две «груши»
Хотя вы, вероятно, не написали ни одной строки кода с блочным стилем, вы должны быть знакомы с этим распространенным кодом JavaScript:
1.1
for (var i = 0; i < 5; i++) {
console.log(i);
}
Мы определяем переменную i непосредственно в цикле for.Обычно мы хотим использовать i только в контексте внутри тела цикла, но все идет не так, как мы хотим, я буду неявно привязан к внешней области видимости (функция области или глобальная объем).
1.2
var a = true;
if (a) {
var b = a * 2;
b = func(b);
console.log(b);
}
function func(b) {
return b + 1;
}
Когда объявленная нами переменная b используется в коде, она используется только в контексте оператора if. Если ее можно ограничить контекстом оператора if, это будет очень значимо, но «идеал очень полный, а теперь он очень тонкий", используйте var для объявления переменной, она везде одинакова, потому что она будет принадлежать внешней области видимости..
Выше кратко описаны две маленькие «груши».
Почему мы надеемся, что переменные могут быть привязаны к их собственной области видимости на уровне блоков, давайте посмотрим на это медленно!
Во-вторых, определение области действия на уровне блоков.
Я верю ребятам здесь, если рядом с вами каждый день сидит интервьюер:
面试官:请简单说一下块级作用域。
你:(思考,首先想一想什么是块级作用域....)???...不知道?
Фактически, для объяснения его можно разделить на две части: объем и уровень блока.
- Объем: Вы также можете установить букву B, чтобы объяснить объем с разных сторон. Если вы считаете, что этого недостаточно, вы также можете поговорить о классификации области (глобальная область, область действия, область действия блока).
- Широкий: набор доступных переменных, функций, объектов и определяет видимость переменных и других ресурсов в области кода.
- Узкий смысл: самая основная функция всех языков программирования - хранить значение переменной и иметь возможность доступа и изменения ее позже.Эта возможность доступа или изменения значения переменной приносит «состояние» в программа. Если нет состояния, гибкость программы будет значительно снижена. Для хранения переменных в программе и доступа к переменным требуется набор хорошо разработанных правил, которые мы называем областью действия.
- Уровень блока: уровень блока javaScript — это блок кода в фигурных скобках {...}, который мы называем уровнем блока.
Подводя итог, можно сказать, что область действия блока — это область, заключенная в {...}. В этой области он ведет себя так же, как и область действия функции.
3. Как создать область на уровне блока
То есть все не написали ни строчки кода ES6, но вы также можете знать, что в блоке кода есть область видимости на уровне блока, содержащая let и const. Но на самом деле есть много способов определить область действия на уровне блоков. Блочные области могут быть созданы задолго до ES6.
3.1 with
function m(obj) {
with(obj) {
a = 2;
console.log(a);
}
console.log(obj);
console.log(obj.a);
}
var obj = {}; m(obj);
with — непонятная конструкция. В JavaScript есть два механизма, которые могут обмануть способ «лексической области видимости». With — один из них. With по существу рассматривает ссылку на объект как область действия, а свойства объекта — как функцию. Идентификатор области видимости обрабатывается, тем самым создавая новую лексическую область видимости (среду выполнения).
3.2 try/catch
try{
undefined();
} catch(err) {
console.log(err);
}
console.log(err);
3.3 let
Это ES6, с которым все знакомы.
var a = true;
if (a) {
let b = a * 2;
b = func(b);
console.log(b);
}
function func(b) {
return b + 1;
}
console.log(b);
Вот небольшое знание, которое может потребовать всеобщего внимания, см. следующий код:
function f() {
console.log(a);
let a = 2;
}
f(); // ReferenceError: a is not defined
Этот код напрямую сообщает об ошибке a не определено. Пусть и const имеют схожие характеристики, что предотвращает продвижение переменной.При выполнении console.log(a) переменная не определена.
- Написано в МДН: в ECMAScript 2015let do not support Variable Hoisting, which means the declarations made using "let", do not move to the top of the execution block.
В MDN думаю, что пусть не существует подъема переменной
- ECMA-262-13.3.1 Объявления Let и Const утверждают: let and const declarations define variables that are scoped to the running execution context's LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated.
Это означает, что даже оператор let в последней строке блока влияет на первую строку блока. это подъем
- ECMA-262: 8.2.1.2 Семантика среды выполнения: EvalDeclarationInstantiation(body, varEnv, lexEnv, strict) пишет: The environment of with statements cannot contain any lexical declaration so it doesn't need to be checked for var/let hoisting conflicts.
Это предложение также косвенно доказывает существование let hoisting.
Этот факт, это будет вопрос, почему вышеуказанная ошибка кода. На самом деле, это не потому, что переменные не приводят к подсказке, а из-за TDZ (временная мертвая зона), вызванная.
В примере:
{
a = 2;
let a;
}
Этот код можно интерпретировать как:
{
let a;// 变量提升
"start TDZ"
a = 2; // 这里在TDZ中间,所以会导致a = 2 报错
a;
"end TDZ"
}
Итак, дело решено: пусть переменная раскрутка отсутствует. Его «переменное поведение при подъеме» связано с TDZ.
так... резюмируя
- пусть объявления поднимаются в верхнюю часть блока
- От вершины блока до оператора инициализации переменной эта область называется TDZ (временная мертвая зона).
- Если вы используете эту переменную в TDZ, JS сообщит об ошибке Обратите внимание, что TDZ не эквивалентен подъему.
3.4 const
В дополнение к let в ES6 также введена константа, которую также можно использовать для создания переменных с блочной областью видимости, но их значения фиксированы (константы). После любого изменения представленияоперации вызовут ошибки.
Преимущества блочной области видимости
4.1 Предотвращение перезаписи внешних переменных внутренними переменными
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
Исходное намерение приведенного выше кода состоит в том, что внешняя часть блока кода if использует внешнюю переменную tmp, а внутренняя часть использует внутреннюю переменную tmp. Однако после выполнения функции f выходной результат не определен, поскольку повышение переменной приводит к тому, что внутренняя переменная tmp перезаписывает внешнюю переменную tmp.
4.2пустая петля
for (let i = 0; i < 5; i++) {
console.log(i);
}
console.log(i);
4.3 Сборка мусора
function func(obj) {
// doSomething
}
var obj = {...};
func(obj);
var bnt = document.getElementById('xxx');
bnt.addEventListener('click', function() {
// doSomething
});
В приведенном выше коде нажмите на элемент, чтобы вызвать событие клика.Объект obj здесь не нужен.Теоретически, когда func выполняется, объект в памяти будет переработан механизмом сборки мусора, но функция щелчка образует область действия, которая охватывает всю область действия замыкания. Весьма вероятно, что движок JavaScript по-прежнему будет поддерживать эту структуру без повторного использования.
function func(obj) {
// doSomething
}
{
let obj = {...};
func(obj);
}
var bnt = document.getElementById('xxx');
bnt.addEventListener('click', function() {
// doSomething
});
Область видимости на уровне блоков позволяет движку ясно понять, что нет необходимости хранить память obj и позволить механизму сборки мусора перерабатывать ее.
V. Резюме
Надеюсь моим друзьям понравятся мои статьи, будем расти вместе, спасибо!
Ссылаться на:Механизм подъема переменных JavaScript
Ссылаться на:es6.ruanyifeng.com/