Skip to main content

Різниця між let, const і var

let і const відрізняються від var блочною областю видимості, забороною повторного оголошення та Temporal Dead Zone замість тихого undefined. Додатково const забороняє перезапис значення, а let і const, на відміну від var, не додають властивість до глобального об'єкта в браузері.

Теорія

TL;DR

  • var, функціональна або глобальна область видимості; let і const, блочна.
  • Усі три піднімаються, але var ініціалізується як undefined, а let і const лежать у TDZ і кидають ReferenceError.
  • Повторне оголошення дозволене лише для var; для let і const це SyntaxError.
  • Перезаписати значення можна у var і let; const дає TypeError.
  • const захищає посилання, а не вміст: властивості об'єкта чи елементи масиву змінювати можна.
  • У браузері var на верхньому рівні стає властивістю window, let і const, ні.

Швидкий приклад

javascript
function demo() { if (true) { var scopedToFunction = 'var'; let scopedToBlock = 'let'; const alsoScopedToBlock = 'const'; } console.log(scopedToFunction); // 'var', visible in the whole function console.log(scopedToBlock); // ReferenceError console.log(alsoScopedToBlock); // ReferenceError } demo();

Основні відмінності

Критерійvarletconst
Область видимостіФункція або глобальнаБлочна ({ ... })Блочна ({ ... })
Підйом (hoisting)Піднімається й ініціалізується як undefinedПіднімається, але не ініціалізується (помилка при зверненні до оголошення)Піднімається, але не ініціалізується (помилка при зверненні до оголошення)
Повторне оголошенняДозволене в одній областіПомилкаПомилка
Перезапис значенняМожнаМожнаНе можна
Додавання до об'єкта window (у браузері)Так (window.varName)НіНі

Область видимості

var, функціональна область видимості. Блок if, for чи просто { ... } для нього не бар'єр: змінна належить найближчій функції або глобальній області.

javascript
if (true) { var a = 10; } console.log(a); // 10 (доступна за межами блока)

let і const, блочна область видимості. Вони існують лише всередині тих фігурних дужок, у яких оголошені.

javascript
if (true) { let b = 20; const c = 30; } console.log(b); // ReferenceError console.log(c); // ReferenceError

let і const «живуть» тільки всередині блока {}.

Саме тому в циклі for із let кожна ітерація отримує власну змінну, а з var, одну спільну на весь цикл:

javascript
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i)); // 3, 3, 3 } for (let j = 0; j < 3; j++) { setTimeout(() => console.log(j)); // 0, 1, 2 }

Hoisting і Temporal Dead Zone

Усі змінні «піднімаються» на початок своєї області видимості, але по-різному. var одразу ініціалізується значенням undefined, а let і const потрапляють у Temporal Dead Zone (TDZ), тимчасову мертву зону, де змінна вже існує, але звертатися до неї ще не можна.

javascript
console.log(a); // undefined (var піднімається й ініціалізується) var a = 5; console.log(b); // ReferenceError (b у TDZ) let b = 10; console.log(c); // ReferenceError (c у TDZ) const c = 15;

TDZ, це не вада, а захист: замість тихого undefined, яке проявиться десь далі як дивний баг, ви отримуєте помилку саме в тому рядку, де припустилися помилки.

Повторне оголошення, перезапис і const з об'єктами

Повторно оголосити змінну в тій самій області можна тільки через var. Перезаписати значення можна у var і let, але не в const.

javascript
var x = 1; var x = 2; // дозволено console.log(x); // 2 let y = 1; let y = 2; // SyntaxError: Identifier 'y' has already been declared const z = 1; z = 2; // TypeError: Assignment to constant variable

Важливий нюанс: const захищає посилання, а не вміст. Об'єкт або масив, на який вказує константа, залишається змінним.

javascript
const user = { name: 'Tim' }; user.name = 'Alex'; // можна змінити властивість console.log(user.name); // 'Alex' user = {}; // TypeError: не можна перепризначити сам об'єкт

Якщо потрібна справжня незмінність вмісту, використовують Object.freeze(user).

Глобальний об'єкт і правило вибору

У браузері var на верхньому рівні створює властивість глобального об'єкта, а let і const, ні.

javascript
var x = 10; let y = 20; const z = 30; console.log(window.x); // 10 console.log(window.y); // undefined console.log(window.z); // undefined

var додає змінну до глобального об'єкта (window, globalThis), через що легко випадково перезаписати чужу глобальну змінну. let і const цього не роблять, тому код стає безпечнішим.

СитуаціяЩо використовуватиЧому
Змінна має змінюватисяletБезпечніше за var, блочна область видимості
Змінна не має змінюватисяconstЯвно показує незмінність
Старий код (до ES6)varЗастаріло, лише для підтримки старих проєктів

Просте правило запам'ятовування:

const, за замовчуванням. let, якщо потрібно змінити значення. var, ніколи в сучасному коді.

Типові помилки

  • Думати, що const робить об'єкт незмінним. Незмінним є лише прив'язка імені до значення; поля об'єкта й елементи масиву спокійно змінюються.
  • Вважати, що let і const не піднімаються. Вони піднімаються, просто до рядка оголошення перебувають у TDZ, звідси ReferenceError, а не undefined.
  • Використовувати var у циклі з асинхронними колбеками. Одна спільна змінна на весь цикл дає класичний результат 3, 3, 3 замість 0, 1, 2.
  • Покладатися на те, що var за межами блока «просто працює». Це джерело випадкових перезаписів і конфліктів імен у великому файлі.
  • Очікувати window.myLet у браузері. Змінні let і const не потрапляють у глобальний об'єкт, тому такий доступ дасть undefined.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.