- Scope
- Hoisting
- TDZ
Scope (область видимости) в JavaScript определяет доступность переменных, функций и объектов в разных частях вашего кода. Существуют три основные области видимости в JavaScript:
Переменная объявляется вне всех функций или блоков. Она доступна везде в коде.
Пример:
let globalVariable = "I am global";
function exampleFunction() {
console.log(globalVariable); // "I am global"
}
exampleFunction();
console.log(globalVariable); // "I am global"Переменные, объявленные внутри функции, доступны только внутри этой функции.
Пример:
function exampleFunction() {
let localVariable = "I am local";
console.log(localVariable); // "I am local"
}
exampleFunction();
console.log(localVariable); // Ошибка: localVariable не определенаПеременные, объявленные с помощью let или const внутри блока {}, доступны только внутри этого блока. Важно: Переменные, объявленные с помощью var, не поддерживают блочную область видимости, а привязываются к функции или глобальной области.
Пример:
if (true) {
let blockScoped = "I am block-scoped";
console.log(blockScoped); // "I am block-scoped"
}
console.log(blockScoped); // Ошибка: blockScoped не определенаОбласть видимости ограничена функцией, а не блоком. Переменная поднимается (hoisting), но ее значение становится доступным только после строки объявления.
function test() {
if (true) {
var testVar = "var scoped";
}
console.log(testVar); // "var scoped"
}
test();Имеют блочную область видимости. Не поднимаются так же, как var.
if (true) {
let testLet = "block scoped";
const testConst = "block scoped const";
}
console.log(testLet); // Ошибка: testLet не определенаЗамыкание (closure) возникает, когда функция запоминает область видимости, в которой она была создана.
Пример:
function outerFunction() {
let outerVariable = "I am from outer scope";
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const closure = outerFunction();
closure(); // "I am from outer scope"Hoisting (поднятие) в JavaScript — это механизм, при котором переменные, функции и классы "поднимаются" (перемещаются) интерпретатором в начало своей области видимости, даже если они были объявлены позже в коде.
Однако, несмотря на то что объявления поднимаются, инициализация переменных и классов остаётся на месте.
Для переменных, объявленных с помощью var, поднимается только объявление, а значение остаётся на месте. Переменные, объявленные через let и const, также поднимаются, но они находятся в "временной мёртвой зоне" (Temporal Dead Zone, TDZ), пока не будут достигнуты строкой объявления.
Объявления функций через function поднимаются целиком (и объявления, и реализации). Функции, определённые через function expression или стрелочные функции (=>), ведут себя как переменные.
Классы поднимаются, но не инициализируются, что приводит к ошибке при их использовании до строки объявления.
console.log(myVar); // undefined (объявление поднято, но значение не присвоено)
var myVar = 10;
console.log(myVar); // 10console.log(myLet); // Ошибка: Cannot access 'myLet' before initialization
let myLet = 20;
console.log(myConst); // Ошибка: Cannot access 'myConst' before initialization
const myConst = 30;Переменные let и const находятся в TDZ, пока не достигнут строки объявления.
greet(); // "Hello!"
function greet() {
console.log("Hello!");
}Функции, объявленные через function, поднимаются вместе с реализацией.
console.log(sayHi); // undefined (переменная объявлена, но значение ещё не присвоено)
var sayHi = function () {
console.log("Hi!");
};
sayHi(); // "Hi!"Для function expressions поднимается только объявление переменной.
const obj = new MyClass(); // Ошибка: Cannot access 'MyClass' before initialization
class MyClass {
constructor() {
this.name = "Class Example";
}
}Хотя класс поднимается, он недоступен до инициализации.
- Используйте let и const вместо var, чтобы избежать неявного поведения.
- Объявляйте переменные и функции в начале их области видимости.
- Избегайте обращения к переменным или функциям до их объявления.
TDZ (Temporal Dead Zone) — это временная мёртвая зона в JavaScript, которая существует для переменных, объявленных с помощью let, const, а также для классов. В этой зоне переменная считается недоступной до того момента, пока не будет достигнута строка её объявления.
TDZ начинается с начала области видимости переменной. Например, для переменной, объявленной в функции, TDZ начинается с начала тела функции.
TDZ заканчивается на строке, где переменная объявлена с помощью let, const или class.
Попытка обратиться к переменной в TDZ вызывает ошибку ReferenceError.
TDZ помогает разработчикам избежать доступа к переменным до их фактического объявления. Это делает поведение кода более предсказуемым и защищённым от ошибок.
{
console.log(myLet); // Ошибка: Cannot access 'myLet' before initialization
let myLet = 10;
console.log(myLet); // 10
}Переменная myLet существует в области видимости с начала блока {}, но она находится в TDZ до строки объявления let myLet = 10;.
{
console.log(myConst); // Ошибка: Cannot access 'myConst' before initialization
const myConst = 20;
console.log(myConst); // 20
}Поведение const аналогично let, с той лишь разницей, что значение переменной const должно быть обязательно присвоено во время объявления.
{
console.log(myFunc); // Ошибка: Cannot access 'myFunc' before initialization
let myFunc = function () {
console.log("Hello!");
};
myFunc(); // "Hello!"
}Функция, объявленная как выражение (function expression), также находится в TDZ, пока не будет выполнена строка с её объявлением.
const instance = new MyClass(); // Ошибка: Cannot access 'MyClass' before initialization
class MyClass {
constructor() {
this.name = "Test";
}
}Классы, как и переменные, находятся в TDZ до строки, где они объявлены.
{
console.log(myVar); // undefined
var myVar = 30;
console.log(myVar); // 30
}Переменная var поднимается, но не попадает в TDZ. Это может приводить к неожиданному поведению.
{
console.log(myLet); // Ошибка: Cannot access 'myLet' before initialization
let myLet = 30;
console.log(myLet); // 30
}С let и const, TDZ предотвращает доступ до строки объявления.
Пока на этом всё. Вы можете найти другие ответы из интернета или документациях.
