Что такое temporal dead zone
Русские Блоги
Вы знаете временную мертвую зону, чтобы лучше использовать переменные JS
Во-первых, простой вопрос. Какой из следующих фрагментов кода приведет к ошибке:
Первый создает экземпляр, а затем определяет используемый класс:
Или вызовите функцию перед определением функции:
Правильный ответ: первый фрагмент кода сообщит ReferenceError: Cannot access ‘Car’ before initialization ошибка. Второй код работает нормально.
Если ваш ответ отличается от приведенного выше или вы догадались, не зная, что за этим стоит, то вам необходимо освоитьВременная мертвая зона (TDZ)знания.
TDZ Управление let 、 const с участием class Наличие грамматики. Способ работы переменных в JS очень важен.
1. Что такое временная мертвая зона
Начнем с простого const Объявление переменной начинается. Сначала объявите и инициализируйте переменную, затем получите к ней доступ, все работает нормально:
Если вы посетите перед заявлением white Переменные, что будет «
В const white = ‘#FFFFFF’ В строке кода перед оператором переменная white родыВременная мертвая зона。
ВTDZ Средний визит white После того, как JS бросает ReferenceError: Cannot access ‘white’ before initialization
Семантика временной зоны нечувствительности запрещает доступ к переменной до ее объявления. Это усиливает последовательность: ничего не использовать до объявления.
2. Заявление затронуто ТДЗ
Взгляните на заявление, затронутое TDZ.
2.1 константные переменные
Как упоминалось ранее, const Переменная находится перед строкой объявления и инициализации.TDZ в:
Мы должны использовать после объявления const переменная:
2.2 пусть переменные
Перед строкой выписки let Заявление декларации также затрагивает TDZ:
Опять же, используйте только после объявления let переменная:
2.3 объявление класса
Как видно во введении, в определении class Его нельзя использовать раньше:
2.4 super () внутри конструктора
Если вы вызываете конструктор super() Перед расширением родительского класса эта привязка находится в TDZ.
В разработке constructor() В звонке super() Нельзя использовать раньше this 。
TDZ рекомендует вызвать родительский конструктор для инициализации экземпляра. После этого экземпляр готов и его можно настраивать в субконструкторе.
2.5 Параметры функции по умолчанию
Параметры по умолчанию существуют в промежуточной области, отделенной от глобальной области и области функции. Параметры по умолчанию также соответствуют ограничениям TDZ.
3. var, функция, оператор импорта
В отличие от приведенного выше утверждения, var с участием function TDZ не влияет на определение. Они продвигаются на вершину текущего диапазона.
Если вы посетите перед заявлением var Переменная, вы получите только одну undefined Переменные
Однако его можно использовать в зависимости от того, где определена функция:
Обычно нас вообще не интересует реализация функции, мы просто хотим ее вызвать. Поэтому иногда имеет смысл вызвать функцию до ее определения.
Интересно, что модуль импорта также был продвинут.
Конечно, рекомендуется import Пишите в начале файла для облегчения чтения и записи.
4. Тип поведения в TDZ
typeof Операторы используются, чтобы определить, определена ли переменная в текущей области.
Поскольку переменная не определена, поэтому typeof notDefined Ценность undefined 。
Но typeof Операторы ведут себя по-разному при использовании переменных во временной мертвой зоне. В этом примере JS выдает ошибку:
Причина этой справочной ошибки заключается в том, что вы можете статически (просто взглянув на код) определить, что переменная была определена.
5. TDZ принимает меры в текущем объеме
Временная мертвая зона влияет на переменные в области действия объявления.
Взгляните на пример:
Есть 2 области применения:
Определите внутреннюю область блока для переменных let
6. Резюме
Вместо этого его можно использовать перед объявлением var Переменная, var Переменные наследуют старое поведение, и их следует избегать.
Автор: Дмитрий Павлутин Переводчик: Front Ash Источник: dmitripavlutin
What is the Temporal Dead Zone (TDZ) in JavaScript?
I know Temporal Dead Zone sounds like a sci-fi phrase. But it’s helpful to understand what the terms and concepts you work with everyday (or want to learn about) mean.
Strap in, because this gets complicated.
Are you aware that in JavaScript we can add < >to add a level of scope wherever we want?
So we could always do the below:
Hopefully, you don’t see this in production code!
I’ve included this detail to make sure that the upcoming examples makes sense (as I didn’t want to assume that everyone knew it).
Two unique variables, with different values.
The above has occurred because the re-declaration of babyAge to 2 is only available inside the if block. Beyond that, the first babyAge is used. Can you see that they are two different variables?
In contrast, the var declaration has no block scope:
One variable with it’s value re-declared.
They throw the error all because of the Temporal Dead Zone.
Temporal Dead Zone explained
This is what the TDZ is: the term to describe the state where variables are un-reachable. They are in scope, but they aren’t declared.
The let and const variables exist in the TDZ from the start of their enclosing scope until they are declared.
You could also say that the variables exist in the TDZ from the place they get bound (when the variable gets bound to the scope it’s inside) until it is declared (when a name is reserved in memory for that variable).
The temporal dead zone captured and catalogued.
But var won’t do that. var is just default initialized to undefined unlike the other declaration.
What’s the difference between declaring and initialising?
Here is an example of declaring a variable and initialising a variable.
Declaring vs Initialising a variable.
Declaring a variable means we reserve the name in memory at the current scope. That is labelled 1 in the comments.
Initialising a variable is setting the value of the variable. That is labelled 2 in the comments.
Or you could always do both on one line. That is labelled 3 in the comments.
Just to repeat myself again: the let and const variables exist in the TDZ from the start of their enclosing scope until they are declared.
Check your answer The hands and age variables both enter the TDZ.
The TDZ for hands ends when it gets declared, the same line it gets set to 2.
The TZ for age ends when it gets declared, and the name reserved in memory (in step 2, where I commented).
Why is the TDZ created when it is?
Let’s go back to our first example:
If we add a console.log inside the TDZ you will see this error:
Why does the TDZ exist between the top of the scope and the variable declaration? What’s the specific reason for that?
It’s because of hoisting.
The JS engine that is parsing and executing your code has 2 steps to do:
Step 1 is where hoisting happens, and this is done by the JS engine. It essentially will move all your variable declarations to the top of their scope. So an example would be:
To be clear, these variables aren’t physically moving in the code. But, the result would be functionally identical to the below:
Just to prove let and const also hoist, here’s an example:
The above snippet is proof that let is clearly hoisted above where it was declared, as the engine alerts us to the fact. It knows name exists (it’s declared), but we can’t access it before it is initialized.
If it helps you to remember, think of it like this.
When variables get hoisted, var gets undefined initialized to its value by default in the process of hoisting. let and const also get hoisted, but don’t get set to undefined when they get hoisted.
More examples of the TDZ
The TDZ can also be created for default function parameters. So something like this:
There’s one more final and fairly advanced example from Erik Arvindson (who’s involved in evolving and maintaining the ECMAScript spec):
One final TDZ example.
You can follow the commented numbers.
In the first line we call the f function, and then try to access the b variable (which throws a ReferenceError because b is in the TDZ).
Why do we have the TDZ?
Dr Alex Rauschmayer has an excellent post on why the TDZ exists, and the main reason is this:
It helps us catch errors.
To try and access a variable before it is declared is the wrong way round, and shouldn’t be possible.
It also gives more expected and rational semantics for const (because const is hoisted, what happens if a programmer tries to use it before it is declared at runtime? What variable should it hold at the point when it gets hoisted?), and was the best approach decided by the ECMAScript spec team.
How to avoid the issues the TDZ causes
Relatively simply, always make sure you define your let s and const s at the top of your scope.
Software Engineer and principal architect @ kealanparr.com
If you read this far, tweet to the author to show them you care. Tweet a thanks
Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started
freeCodeCamp is a donor-supported tax-exempt 501(c)(3) nonprofit organization (United States Federal Tax Identification Number: 82-0779546)
Donations to freeCodeCamp go toward our education initiatives and help pay for servers, services, and staff.
ES6: Let, Const и «Временная мёртвая зона» (ВМЗ) изнутри
Как и в прошлых статьях, рекомендую вам установить Babel и повторять за мной, копируя примеры с помощью интерактивной оболочки REPL, либо командной строки babel-node и файла. Это поможет гораздо лучше усвоить идеи, обсуждаемые в серии. Если вы не из тех, кто любит устанавливать что-либо на свой компьютер, то вам есть смысл залезть на CodePen и кликнуть иконку с шестерёнкой для JavaScript — у него есть препроцессор Babel, который с лёгкостью позволяет опробовать ES6. Ещё одна довольно полезная альтернатива, это использовать онлайновый REPL для Babel — он показывает скомпилированный ES5-код справа от ES6-кода, чтобы быстро сравнить.
Оператор Let
Как только вы откроете для себя штуку, называемую поднятием, всё сразу проясняется. Смысл поднятия в том, что переменные переносятся из места объявления в коде в верх их области видимости. К примеру, есть такой код:
Причина, по которой это приходится учитывать — то, что, как мы знаем, область видимости var ограничена функцией. В сочетаниии с поднятием это означает, что на самом деле наш код соответствует чему-то вроде следующего примера.
Нравится нам или нет (либо мы просто привыкли к этому — по себе знаю), но это явно запутаннее, чем когда область видимости переменных ограничена блоком. Блочная область видимости работает на уровне скобок, а не на уровне функции.
Однако, с var по-прежнему можно достучаться до переменной снаружи этих многочисленных блоков и не получить ошибку. Но бывает весьма кстати, если в такой ситуации выскочит ошибка. Тем более, если хотя бы одно из перечисленного верно.
Так как же этот let работает?
Оператор let — альтернатива var. Он следует правилам блочной области видимости, а не область видимости, ограниченная функцией — правилам по умолчанию. Это значит, что нам больше не нужны целые функции ради новой области видимости — блока <> достаточно!
Вот это уже интереснее. Пока я писал этот пример, то размышлял: «Ладно, но если мы теперь объявляем функцию внутри блока и получим доступ к ней снаружи этого блока, то наверняка всё пойдет наперекосяк». Исходя из опыта с ES5, я ожидал, что следующий фрагмент кода должен работать (и в ES5 это так), но в ES6 он ломается. И это была бы проблема, ведь при поднятии функции из блока наружу было бы слишком легко нарушить инкапсуляцию свойств, которые должны быть видимы лишь внутри него. Я не ожидал, что это выбросит ошибку.
Оказывается, это был не баг в Babel, а на самом деле (весьма отрадное) изменение в семантике языка ES6.
Цитата из твиттера:
Ингвар Степанян (@RReverser), твит
@ nzgb @ rauschma @ sebmck ЕМНИП, так и должно быть — ES6 наконец определил, что функции в блоках должны вести себя как с блочной областью видимости
Я планирую использовать var почти всё время, a let там, где ни к чему бессмысленное поднятие переменных, которые по логике принадлежат блоку условия или цикла, в начало всей функции.
Временная мёртвая зона и Дары Смерти
Последнее, что касается let — таинственное понятие под названием «Временная мёртвая зона» (ВМЗ) — уу… как страшно, знаю.
Попросту говоря: следующий код выбросит ошибку.
Заметьте, что даже если при первом объявлении there не присваивать ей значения, семантика для этих примеров не изменится. Код ниже всё ещё выкидывает ошибку, поскольку мы по-прежнему пытаемся обратиться к there до выхода из ВМЗ.
Единственная хитрость, о которой стоит помнить (когда дело касается ВМЗ), что функции до своего первого выполнения действуют как «чёрные ящики», поэтому вполне нормально размещать there внутри функций, которые не выполняются, пока мы не выйдем из ВМЗ.
Весь смысл ВМЗ — легче вылавливать ошибки там, где обращение к переменной до её объявления приводит к неожиданностям. Это зачастую происходило в ES5 из-за поднятия и непродуманных соглашений о стиле кода. Учтите, что поднятие применяется и к let тоже — это значит, что переменные будут созданы, когда мы зайдем в область видимости (и ВМЗ появится), но они будут недоступны до тех пор, пока выполнение кода не дойдёт до места фактического объявления переменной, и в этот момент мы выходим из ВМЗ и вправе делать с переменной что угодно.
Оператор Const
А также есть пара основных отличий.
После объявления const невозможно изменить ссылку или литерал, которые ему присвоены.
Однако, можно изменять саму ссылку. Она не становится неизменной. Чтобы сделать само значение неизменный, вам пришлось бы использовать Object.freeze.
Я считаю, что const великолепен, поскольку позволяет отмечать то, что нужно сохранить в неизменности. Представьте, следующий код, встречающийся в некоторых ситуациях — извиняюсь за бурную фантазию.
Если бы в коде выше groceries были константой, то повторное присваивание было бы гораздо легче обнаружить. Ура, ES6! В будущем я точно буду пользоваться const сплошь и рядом, вот только освоюсь с ним получше.
Теперь дело только за практикой
P.S. Это тоже может быть интересно:
Если вам понравилась статья, поделитесь ей!
Почему существует временная мертвая зона?
Я знаю что такое временная мертвая зона (TDZ), но Я не могу понять цель его существования.
Может ли кто-нибудь объяснить мне, почему он был создан?
Какова логика его создания ReferenceError или SyntaxError вместо возврата undefined?
ReferenceError:
SyntaxError:
Undefined:
Имеет смысл, чтобы переменная существовала с момента ее определения. Из-за того, что переменные из внешней области доступны в пределах вложенных областей, следующий код очень запутан:
Переменная i по-прежнему существует после цикла for благодаря переменным функции. Именно поэтому ключевое слово var позволяет вам определить переменную дважды. Это было бы непрактично, если бы вы были вынуждены писать var только один раз. С переменной let эта “свободная” функция становится бесполезной, поскольку эти переменные должны быть освобождены, как только они больше не нужны.
В 2-м утверждении вы определили переменную два раза. js не позволяет вам определять какую-либо переменную более одного раза в той же области блока.
В третьем выражении, поскольку он показывает ошибку в первой функции, что ваша переменная не определена. По умолчанию это undefined. и вы можете использовать переменную undefined.
Если вы изучите документацию по тем исключениям, которые вы связали в своем вопросе, вы можете увидеть причину, о которой, как я думаю, здесь не обращалось.
Первое примечание: следует отметить, что исключений в EMCAScript не было до версии 3. var явно превосходит эту языковую особенность. почему var и let отличаются друг от друга, во многом объясняется тем, что исключения были доступны, когда были введены, а не когда var был введен. Эта история подчеркивает все это. 1999 год тоже был занят!
В любом случае, в шестерни. Посмотрите, что здесь происходит:
Ошибка, затем код вспахивает. Можем ли мы поймать это и разобраться с ним?
За кулисами этот код выглядит следующим образом:
В каждой точке примера D somethingUndeclared ничего. Это всегда мертвая зона. Я не уверен, какой выпуск EMCAScript в вышеприведенном коде начал генерировать исключения, но он меньше нарушает его, потому что эта ситуация всегда будет ошибкой.
Который подводит нас к заданному вопросу: “Почему бы не снять бандайду, разобраться с перерывом в БК ради последовательности в языке?” Ответ на это потому, что достаточно хорошо, как правило, достаточно хорошо. Есть миллионы строк javascript, управляющих аккордеонами и галереями изображений, а также другие колокола и свистки UI. Один выбирает более зрелый набор языковых функций, когда EMCAScript выполняет критически важные роли. Или вам просто не нравится неряшливый код для вашей сладкой навигации на вкладке. Согласованность на языке не стоит нарушать весь код, который достаточно хорош, чтобы делать то, что ему нужно делать большую часть времени. Представьте себе горы достаточно хороших, которые накопились, поскольку было возможно даже исключение на этом языке (’99).
Почему существует временная мертвая зона?
Я знаю что такое временная мертвая зона ( TDZ ), но я не могу понять цель его существования.
Может кто-нибудь объяснить мне, почему он был создан?
ReferenceError:
SyntaxError:
Не определено:
4 ответа
Имеет смысл, чтобы переменная существовала с момента ее определения. Из-за того, что переменные из внешней области видимости доступны во вложенных областях, следующий код очень сбивает с толку:
Переменная i по-прежнему существует после цикла for благодаря переменным в функциональной области. Именно поэтому ключевое слово var позволяет вам определять переменную дважды. Это было бы непрактично, если бы вы были вынуждены написать var только один раз. С переменной let эта «свободная» функция становится бесполезной, поскольку эти переменные должны быть освобождены, как только они больше не нужны.
Когда вы вызываете функцию в большинстве языков программирования, среда выполнения создает пространство в памяти для переменных, которые вам понадобятся. Здесь нет способа определить, понадобится ли переменная i без фактического выполнения кода, поскольку она находится внутри блока if. Тем не менее, поскольку JS имеет переменные в области функций, он должен создавать переменную с самого начала функции. В случае переменных let это не требуется.
Что касается причины, по которой typeof someundefinedvar возвращает значение undefined, это потому, что вам нужен способ проверки переменных, которые могли быть заявлено в наружных границах. Тем не менее, вам не нужна эта функция для переменных, которые имеют область видимости. Переменные let предназначены для немедленного использования и выбрасывания.
В приведенном выше заявлении вы не определили переменную a и используете ее. В java-скрипте необходимо определить переменную. эта переменная является ссылкой на ваше значение, поэтому показывает неопределенную ошибку ссылки.
Во втором утверждении вы определили переменную два раза. js не позволяет вам определять какую-либо переменную более одного раза в одной и той же области видимости блока.
В третьем утверждении, поскольку в первой функции выдается ошибка, что ваша переменная не определена. По умолчанию он не определен. и вы можете использовать неопределенную переменную.
Первое замечание: стоит упомянуть, что исключения не существовали в EMCAScript до выпуска 3. var, очевидно, намного предшествует этой языковой функции. почему var и let различаются в значительной степени из-за того, что исключения были доступны при введении let, а не при введении var. Эта история подчеркивает все это. 1999 год тоже был насыщенным!
Во всяком случае, в передачах. Посмотрите, что здесь происходит:
Ошибка, затем код вспыхивает. Можем ли мы поймать это и справиться с этим?
За кулисами этот код выглядит следующим образом:
Если в какой-то другой части той же области ИЛИ родительские области somethingUndeclared не определены, возможно, для какой-то другой цели. Или, может быть, код var somethingUndeclared; лежит где-то в области видимости или родительских областях по какой-то причине, так что в аной код выше. Это аргумент в пользу использования let или const почти исключительно.
Что побуждает нас перейти к нерешенному вопросу: «Почему бы не снять бинты, разобраться с разрывом до н.э. ради последовательности в языке?» Ответ на это потому, что достаточно хороший, как правило, достаточно хорош. Существуют миллионы строк javascript, управляющих аккордеонами, галереями изображений и прочими прибамбасами пользовательского интерфейса. При выборе EMCAScript для выполнения критически важных ролей выбирается более зрелый набор языковых функций. Или вам просто не нравится небрежный код для вашей сладкой вкладкинавигации. Согласованность в языке не стоит нарушать весь код, который достаточно хорош, чтобы делать то, что ему нужно делать большую часть времени. Представьте себе горы достаточно хороших, которые накопились, поскольку на этом языке даже можно было сгенерировать исключение (’99).
Когда нам нужно сделать то, что он должен делать все время, мы можем использовать эти функции. Когда undefined = 100; может оказаться катастрофой для какого-либо файла в проекте, мы можем включить исключения. Когда прогрессивное улучшение завершается неудачно и мы не получаем всплывающих подсказок, у нас получается менее приятный пользовательский интерфейс, чем мы надеялись. У var и let разные плечи и вес на плечах, поэтому они всегда будут действовать по-разному.