Область видимости говорит, где в коде переменная «живёт» и где её можно использовать. Если не учитывать правила для var/let/const, код будет выдавать странные значения или падать с ошибками. Дальше — только факты и примеры, которые можно сразу проверить.
var: живёт по функции, всплывает, разрешает повтор
Что это значит на практике:
- Виден во всей функции, блок
{}его не ограничивает. - Объявление всплывает наверх функции, но до присваивания значение будет
undefined. - Можно два раза написать
var xв одной области — ошибки не будет.
Пример 1: var внутри if — виден снаружи
function demoVar() { if (true) { var x = 10; } console.log(x); // 10 } demoVar();
Здесь x доступен после if, потому что для var блок не создаёт отдельную область.
Пример 2: цикл с var — счётчик остаётся после цикла
for (var i = 0; i < 3; i++) {} console.log(i); // 3
Переменная i продолжает существовать после цикла. Это легко ломает логику, если дальше в коде есть своя i.
Пример 3: обращение до объявления → undefined
console.log(z); // undefined var z = 5;
Фактически JS обрабатывает это так:
var z; console.log(z); // undefined z = 5;
Из‑за этого бывает трудно понять, почему значение не то.
Пример 4: повторное объявление var без ошибки
var a = 1; var a = 2; console.log(a); // 2
В большом файле легко случайно продублировать имя и незаметно поменять значение.
let: живёт только в блоке, нельзя повторно объявить, до объявления — ошибка
Что это значит на практике:
- Область — блок
{}:if,for,while, любые фигурные скобки. - Нельзя два раза объявить
let xв одном блоке — будет ошибка. - До строки объявления переменная недоступна: попытка прочитать вызовет
ReferenceError, а неundefined.
Пример 1: let внутри if — снаружи его нет
function demoLet() { if (true) { let y = 20; } // console.log(y); // ReferenceError: y is not defined } demoLet();
Блок реально изолирует переменную.
Пример 2: цикл с let — счётчик не виден после цикла
for (let j = 0; j < 3; j++) {} // console.log(j); // ReferenceError: j is not defined
Цикл не «оставляет мусор» снаружи.
Пример 3: нельзя дважды объявить let в одном блоке
let b = 1; // let b = 2; // SyntaxError: Identifier 'b' has already been declared
Это защищает от случайных перезаписей.
Пример 4: до объявления трогать нельзя
// console.log(c); // ReferenceError: Cannot access 'c' before initialization let c = 3;
Если порядок перепутан — сразу ошибка, её проще заметить.
const: как let, но нельзя переназначить
Что это значит на практике:
- По области видимости ведёт себя как
let(блок{}). - Нельзя сделать
const x = ...и потомx = .... - Для объектов и массивов можно менять свойства/элементы, но нельзя присвоить новую ссылку.
Пример 1: нельзя переназначить const
const d = 4; // d = 5; // TypeError: Assignment to constant variable
Пример 2: const в блоке — снаружи не виден
if (true) { const e = 5; } // console.log(e); // ReferenceError: e is not defined
Пример 3: содержимое менять можно, ссылку — нет
const arr = [1, 2]; arr.push(3); // ок: [1, 2, 3] // arr = [4, 5]; // ошибка const obj = { name: 'test' }; obj.name = 'new'; // ок // obj = {}; // ошибка
Где чаще всего случаются проблемы
varв цикле: счётчик остаётся снаружи и случайно влияет на дальнейший код.- Обращение к переменной до объявления: с
varполучаешьundefinedи долго ищешь ошибку; сlet/constсразу падает с понятной ошибкой. - Повторное объявление:
varтихо перезапишет значение,let/constне даст этого сделать. - Ожидание, что
constделает объект «неизменяемым»: на деле он защищает только ссылку, а не содержимое.
