Временная мертвая зона (TDZ – Temporal Dead Zone) в JS
Временная мертвая зона (Temporal Dead Zone) – термин, обозначающий состояние, в котором переменные недоступны. Они находятся в области видимости (scope), но не объявлены (not declared).
Переменные объявленные через let
и const
существуют в области TDZ от начала их в области видимости до момента их декларирования (объявления).
{
//***
//This is the temporal dead zone for the age variable!
//Если мы обращаемся к age тут, то мы получаем ReferenceError:
console.log(age); //Uncaught ReferenceError: Cannot access 'age' before initialization
// This is the temporal dead zone for the age variable!
//***
let age; // Объявление переменной. Теперь TDZ больше нет. Т.е. как только переменная декларирована (объявлена), то TDZ для этой переменной пропадает.
age = 27;
}
var – исключение:
В JavaScript переменные, объявленные с использованием var
, не имеют так называемой временной мёртвой зоны (Temporal Dead Zone, TDZ).
Переменные var
существуют с начала их охватывающей области видимости (функции или глобальной области видимости), и они инициализируются значением undefined
console.log(age) //uderfinded. для var нет понятия TDZ
var age;
age = 28;
В чем разница между объявлением (declaration) и инициализацией (inicialization)?
function scopeExample() {
let age; // 1. Объявление (Declaring) переменной означает, что мы резервируем имя в памяти в текущей области видимости (scope).
age = 20; // 2. Инициализация переменной (Initialising a variable) — это установка значения переменной (setting the value of the variable).
let hands = 2; // 3. также мы можем совместить 1. и 2.
}
Примеры, где можно встретить TDZ:
function createTDZ(a=b, b) {
}
createTDZ(undefined, 1);
//Выведет: Cannot access 'b' before initialization
//Поскольку при вычислении значения переменной a, идет обращение к переменной b, которая еще не пропарсена движком JS.
let tdzTest = tdzTest;
//ReferenceError: Cannot access 'tdzTest' before initialization
Но аналогичный код с var уже не вызовет ошибки:
var tdzTest = tdzTest; //underfined
И заключительный пример от Erik Arvindson, который участвует в разработке и поддержке спецификации ECMAScript:
let a = f(); // 1
const b = 2;
function f() { return b; } // 2, b is in the TDZ
В первой строке мы вызываем f
функцию, а затем пытаемся получить доступ к b
переменной (которая выдает ошибку ReferenceError
. Поскольку b
находится в TDZ).
Зачем нам нужен TDZ?
Alex Написал статью, в которой рассказывает об этом.
- Это помогает нам ловить ошибки;
- Попытка получить доступ к переменной до того, как она будет объявлена, является неправильным способом и не должна быть возможной;
Избежать ошибок, связанных с TDZ довольно просто, достаточно объявлять переменные в верху области видимости.
На основе: https://www.freecodecamp.org/news/what-is-the-temporal-dead-zone/
Задачи:
Что выведет данный код?
Взято с: https://learn.javascript.ru/task/let-scope
let x = 1;
function func() {
console.log(x); // ?
let x = 2;
}
func();
Ответ
Переменная находится в «неинициализированном» («uninitialized») состоянии с момента входа в блок кода (или функцию). И остается неинициализированной до соответствующего оператора let. Другими словами, переменная технически существует, но не может быть использована до let.
function func() {
// локальная переменная x известна движку с самого начала выполнения функции,
// но она неинициализированна ("uninitialized") до let ("мёртвая зона")
// следовательно, ошибка
console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 2;
}