@thefourtheye правильно говорит, что эти переменные не могут быть доступны до их объявления. Тем не менее, это немного сложнее, чем это.
Переменные объявлены с let
или const
нет? Что на самом деле здесь происходит?
Все декларации ( var
, let
, const
, function
, function*
, class
) являются "взвалили" в JavaScript. Это означает, что если имя объявляется в области, в этой области идентификатор всегда будет ссылаться на эту конкретную переменную:
x = "global";
// function scope:
(function() {
x; // not "global"
var/let/… x;
}());
// block scope (not for `var`s):
{
x; // not "global"
let/const/… x;
}
Это верно как для функциональных, так и для блочных областей 1 .
Разница между var
/ function
/ function*
декларациями и let
/ const
/ class
декларациями заключается в инициализации .
Первые инициализируются с помощью функции undefined
или (генератора) справа, когда привязка создается в верхней части области. Однако лексически объявленные переменные остаются неинициализированными . Это означает, что возникает ReferenceError
исключение при попытке доступа к нему. Он будет инициализирован только после вычисления оператора let
/ const
/ class
, все до (выше), которое называется временной мертвой зоной .
x = y = "global";
(function() {
x; // undefined
y; // Reference error: y is not defined
var x = "local";
let y = "local";
}());
Обратите внимание, что let y;
оператор инициализирует переменную с помощью undefined
like let y = undefined;
.
Временная мертвая зона не является синтаксическим расположение, а , скорее, время между переменным (масштабом) созданием и инициализацией. Ссылка на переменную в коде над объявлением не является ошибкой, если этот код не выполняется (например, тело функции или просто мертвый код), и будет выдано исключение, если вы получите доступ к переменной до инициализации, даже если доступ код находится ниже объявления (например, в объявлении поднятой функции, которое вызывается слишком рано).
Есть ли разница между let
и const
в этом вопросе?
Нет, они работают так же, как считается подъем. Единственная разница между ними заключается в том, что const
муравей должен быть и может быть назначен только в части инициализации объявления ( как недопустимые переназначения const one = 1;
, так const one;
и последующие, например one = 2
).
1: var
объявления все еще работают только на уровне функций, конечно
let foo = () => bar; let bar = 'bar'; foo();
иллюстрирует, что все декларации являются эффектом подъема еще лучше, потому что это не очевидно из-за временной мертвой зоны.const
лайкlet
- это недостаток дизайна. В пределах области,const
должны были быть сделаны, чтобы быть поднятыми и точно инициализированными вовремя, когда к нему обращаются. На самом деле, они должны иметь ключевое слово aconst
, alet
и другое, которое создает переменную, которая работает как «только для чтения»let
.Цитирование спецификации
let
иconst
деклараций ECMAScript 6 (ECMAScript 2015) ,Итак, чтобы ответить на ваш вопрос, да,
let
иconst
поднять, но вы не можете получить к ним доступ до того, как фактическое объявление будет оценено во время выполнения.источник
ES6
вводитLet
переменные , которые придумываютblock level scoping
. ПокаES5
у нас не былоblock level scoping
, поэтому переменные, которые объявляются внутри блока, всегда должны бытьhoisted
на уровне функций.В основном
Scope
относится к тому, где в вашей программе видны ваши переменные, что определяет, где вам разрешено использовать объявленные вами переменные. КромеES5
тогоglobal scope,function scope and try/catch scope
,ES6
мы также получаем область видимости на уровне блоков, используя Let.var
ключевого слова, она известна всей функции с момента ее определения.Когда вы определяете переменную с помощью
let
оператора, она известна только в определенном блоке.Если вы запустите код, вы увидите, что переменная
j
известна только в,loop
а не до и после. Тем не менее, наша переменнаяi
известна вentire function
с того момента, как она определена.Есть еще одно большое преимущество использования let, поскольку оно создает новую лексическую среду, а также связывает новую ценность, а не сохраняет старую ссылку.
Первый
for
цикл всегда печатает последнее значение, сlet
его помощью создается новая область видимости и связываются свежие значения, выводящие нас на печать1, 2, 3, 4, 5
.В сущности
constants
, все работает такlet
, как будто их различие не может быть изменено. В константах мутация разрешена, но переназначение не допускается.Если константа ссылается на
object
, она всегда будет ссылаться на,object
ноobject
сама может быть изменена (если она изменчива). Если вы хотите иметь неизменныйobject
, вы можете использоватьObject.freeze([])
источник
Из веб-документов MDN:
В ECMAScript 2015
let
иconst
были подняты, но не инициализированы. Ссылка на переменную в блоке до объявления переменной приводит к тому,ReferenceError
что переменная находится во «временной мертвой зоне» с начала блока до обработки объявления.источник
в es6, когда мы используем let или const, мы должны объявить переменную перед их использованием. например. 1 -
например. 2-
источник