2017-01-10 2 views
0

Следующий код генерирует ReferenceError 'a не определен'.Определенная переменная в внешней области не определена во внутренней области

{ 
    let a = 'a1'; 
    { 
     console.log(a); 
     let a = 'a2'; 
    } 
} 

Как и следующий.

{ 
    const a = 'a1'; 
    { 
     console.log(a); 
     const a = 'a2'; 
    } 
} 

Если вы используете объявления var, это работает так, как я ожидаю. (Ошибка при ошибке и «a1» зарегистрированы.)

Мне становится еще труднее понять, когда я пытаюсь проанализировать следующий код.

{ 
    let a = 'a1'; 
    { 
     console.log(a); 
     var a = 'a2'; 
    } 
} 

Он выбрасывает синтаксический обрыв, «Идентификатор« a »уже объявлен».

Naïvely Я ожидал, что идентификатор будет затенен только после Объявление let или const, как и поведение let в Clojure или let * в Racket. Как described clearly on MDN, это не так, как это работает.

Но Почему работает ли это так? Почему у Racket есть как let, так и let * form?

+0

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let – Teemu

+0

Спасибо за ссылку, но она не отвечает на мой вопрос. Я понимаю, что это работает, но не _why_ эта модель выбрана. Это из-за проблем с производительностью? –

+1

SO - это не место, где можно задать _why_ язык имеет определенную функцию или поведение. Спросите [TC-39] (https: // www.ecma-international.org/memento/TC39-RF-TG.htm), они знают без спекуляций. Я мог бы немного догадаться. Может быть, механизм подъема был настолько важен, что он предпочтительнее внешних переменных? – Teemu

ответ

1

Это вызван грузоподъемным внутренняя let или const к верхней части блока (MDN), а также создать Temporal Мертвой зоны.

В ECMAScript 2015 давайте вернем переменную в верхнюю часть блока . Однако, ссылаясь на переменную в блоке перед объявлением переменной , возникает ссылка ReferenceError. Переменная находится в «временной мертвой зоне» с начала блока до обработки декларации .

Причина в этом проста - тихий отказ от ошибки бросания.

В этом примере аналогичная установка дает результат как undefined из-за подъемника var. Это бесшумная ошибка, и отладка может быть очень сложной.

{ 
 
    var a = 'a1'; 
 
    (function() { 
 
     console.log(a); 
 
     var a = 'a2'; 
 
    })(); 
 
}

Если вы будете использовать let или const ошибка будет выброшено:

{ 
 
    let a = 'a1'; 
 
    (function() { 
 
    console.log(a); 
 
    let a = 'a2'; 
 
    })(); 
 
}

Вы можете найти более подробную информацию о временной мертвых зона в статье TEMPORAL DEAD ZONE (TDZ) DEMYSTIFIED.

+0

Спасибо за отличный совет! –

+0

Добро пожаловать :) –

Смежные вопросы