Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Різниця між let, const і var». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`var` має функціональну область видимості, а `let` і `const`, блочну: вони живуть тільки всередині `{ ... }`.** Усі три оголошення піднімаються (hoisting), але `var` одразу ініціалізується значенням `undefined`, а `let` і `const` потрапляють у Temporal Dead Zone, тому звернення до них до рядка оголошення кидає `ReferenceError`. `var` можна повторно оголосити в тій самій області, `let` і `const`, ні (`SyntaxError`). Значення `var` і `let` можна перезаписати, а `const`, ні (`TypeError`), при цьому `const` захищає саме посилання, а не вміст об'єкта чи масиву. У браузері `var` на верхньому рівні додає властивість до глобального об'єкта `window`, а `let` і `const` цього не роблять, що робить код безпечнішим. ```javascript if (true) { var a = 10; let b = 20; } console.log(a); // 10 console.log(b); // ReferenceError: b is not defined ``` **Ключове:** `const` за замовчуванням, `let` коли значення справді змінюється, `var` у сучасному коді не використовують.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`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(); ``` ### Основні відмінності | Критерій | `var` | `let` | `const` | | --- | --- | --- | --- | | **Область видимості** | Функція або глобальна | Блочна (`{ ... }`) | Блочна (`{ ... }`) | | **Підйом (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`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.