Область блока ES6

внешний интерфейс WeChat Безопасность JavaScript

Добро пожаловать в гостиперсональный сайт

объем

Область действия относится к области, в которой действует переменная.В Javascript есть две области видимости:

  • глобальная область
  • объем функции

переменное продвижение

Подъем считается пониманием того, как контексты выполнения (особенно этапы создания и выполнения) работают в Javascript. Конкретная производительность заключается в том, что все переменные, объявленные через var, будут перемещены в начало текущей области.

function foo() {
    console.log(temp); 
}

function bar() {
    console.log(temp);  
    var temp;
}

foo(); // ReferenceError: temp is not defined
bar(); // undefined

Видно, что объявление с var не сообщит об ошибке. Потому что на самом деле функциональная панель эквивалентна

function bar() {
    var temp;
    console.log(temp);
}

Большинство языков с C-подобным синтаксисом имеют область видимости на уровне блоков. Все переменные, определенные в блоке кода (набор операторов, заключенных в пару фигурных скобок), не видны за пределами блока кода. Переменные, определенные в блоке кода, будут освобождены после выполнения блока кода. Это хорошая вещь.

К сожалению, даже несмотря на то, что код Javascript, кажется, поддерживает область видимости на уровне блоков, Javascript этого не делает (из-за подъема переменных). Эта путаница может быть источником ошибок.

Итак, let и const указаны в ES6 для поддержки области на уровне блоков. Однако правда ли, что улучшения нет, часть временной мертвой зоны вы видите ниже.

let

let можно понимать как «более совершенный var», и его использование очень простое;

let foo = 3;

Метод использования в основном такой же, как у var, а объявленная переменная доступна только в своем блоке и подблоке, что также совпадает с var. Основное различие между ними состоит в том, что областью действия переменной, объявленной с помощью var, является вся объемлющая функция.

function foo() {
    if(true) {
        var temp = 5;
         console.log(temp);
    }
    
    console.log(temp);
}

function bar() {
    if(true) {
        let temp = 5;
        console.log(temp);
    }
    
    console.log(temp);
}

foo(); // 5 和 5
bar(); // 5 和 "ReferenceError: temp is not defined

Областью действия переменной, объявленной с помощью let, является только внешний блок, а не вся внешняя функция.

Мы можем воспользоваться этой функцией в качестве альтернативы немедленно выполняемым функциям (IIFE).

// IIFE
(function(){
    var temp = xxx;
    /*
        other code
    */
}())

// 块级
{
    let temp = xxx;
    /*
        other code
    */
}

const

Использование const похоже на let, но константа должна быть инициализирована, иначе будет выдано сообщение об ошибке.

const temp = 4;

// 没有初始化报错
const t; // SyntaxError: Missing initializer in const declaration

Const — это область на уровне блока. Семантика const и let аналогична. Они используются для объявления констант. После объявления их нельзя изменить. Стоит отметить, что переменная, объявленная const, записывает указатель, и указатель не может быть изменен.Если объект, объявленный const, является объектом, содержимое объекта все еще может быть изменено.

// 重新赋值声明导致报错
const PI = 3.14;
PI = 3.1415926; // TypeError: Assignment to constant variable.

// 给对象增加属性不会导致 obj 的指针变化,所以不会报错
const obj = { foo: 2 };
obj.bar = 3;
console.log(obj); // {foo: 2, bar: 3}

Временная мертвая зона

Для переменной, объявленной с помощью let или const, до поступления объявления доступ к переменной приведет к ошибке, и даже typeof, который всегда считался безопасным, больше не является безопасным.

// TDZ1
function foo() {
    // TDZ 开始
    console.log(typeof temp);
    let temp = 5; // TDZ 结束
}

foo(); // ReferenceError: temp is not defined

Сообщается об ошибке ReferenceError. Если объявлено с помощью var, вывод temp должен быть неопределенным. Область от первой строки блока, где объявляется переменная, объявленная с помощью let, до объявления переменной называется переходной мертвой зоной (TDZ). Любое использование этих переменных в этой области приведет к ошибке.

// TDZ2
function bar() {
    console.log(typeof temp);
}

bar(); // undefined

Когда вы думаете о двух приведенных выше примерах, вы думаете, что-нибудь приходит на ум?

Когда temp не объявлен с let в функции, temp не определен, и он должен быть temp перед объявлением let, но функция foo сообщает об ошибке, которая доказывает, что даже если объявление let не достигнуто, оно все еще использует let It работал раньше. Означает ли это, что let также имеет улучшение (это улучшение не является улучшением var, а только оказывает влияние), но при использовании TDZ сообщается об ошибке, а не undefined.

На самом деле, когда JS-движок проверяет следующий блок кода на наличие объявлений переменных, он поднимает объявление в начало функции или глобальной области видимости для переменной, объявленной как var, и помещает объявление во временное мертвое состояние для let или постоянная площадь. Любая попытка доступа к переменной в переходной мертвой зоне приведет к ошибке «времени выполнения». Только когда достигается оператор объявления переменной, переменная удаляется из временной мертвой зоны и становится безопасной для использования.

Не повторяйте декларации

Внутри одного блока let и const не могут объявлять один и тот же идентификатор. К запрещенным ситуациям относятся:

  • пусть или const и пусть или const
  • var и let или const
  • параметры функции с помощью let или const
// let 和 let
let foo = 1;
let foo = 2;

// let 和 const
let foo = 1;
const foo = 2;

// var 与 let
var foo = 1;
let foo = 2;

// 函数参数与 let
function bar(foo) {
    let foo = 1;
}

В вышеуказанных случаях будет сообщено о SyntaxError. Но разрешается объявлять одну и ту же переменную с помощью let во вложенных областях видимости.

var foo = 1;

{
    // 不会报错
    let = 2;
    // other code
}

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

function foo() {
    var bar = 1;
    {
        let bar = 2;
    }
    
    console.log(bar);
}

function zoo() {
    var bar = 1;
    {
        var bar = 2;
    }
    
    console.log(bar);
}

foo(); // 1
zoo(); // 2

Лучшие практики

На этапе разработки ES6 общепринятым способом объявления переменных является использование let вместо var по умолчанию. . Для большинства JS-разработчиков let ведет себя так, как должен вести себя var, поэтому используйте let напрямую. Замена var более логична. В этом случае вы должны использовать const для переменных, которые необходимо защитить.

Используйте const по умолчанию и используйте let, только если вы знаете, что значение переменной необходимо изменить. Это обеспечивает неизменность кода на базовом уровне, что помогает предотвратить определенные типы ошибок.

мыслительные вопросы

Два вопроса для размышления, вы можете ответить на них в комментариях, а я изложу свои мысли в комментариях позже.

// 思考题 1
switch (x) {
  case 0:
    let foo;
    break;
    
  case 1:
    let foo; // TypeError for redeclaration.
    break;
}

// 思考题 2
function bar(){
   var foo = 1;
   if (true) {
      let foo = (foo + 2); 
   }
}
bar();

Всем привет, я Тао Венг, говорю за себя!

Личный публичный аккаунт WeChat

个人微信公众号