Блочная область видимости
Чему вы научитесь:
- определять, где в программе видна переменная
let,constилиvar; - объяснять, почему
varвыше своей строки хранитundefined, аletтам останавливает программу; - замечать затенение и понимать, чьи переменные видит функция;
- включать строгий режим, чтобы опечатка в имени стала ошибкой.

Представьте квартиру, где у каждой комнаты стены из тонированного стекла. Изнутри комнаты видно и её саму, и коридор за стеклом. А из коридора внутрь комнаты заглянуть нельзя.
Вещь, которую оставили в комнате, существует только для тех, кто в этой комнате находится. Переменные в JavaScript устроены похоже: где переменную объявили, там её и видно.
Но у разных слов объявления «комнаты» разного размера. Здесь в одной ветке if объявлены две переменные, а после ветки прочитать можно только одну из них:
function show(n) {
if (n > 0) {
var a = n;
let b = n * 2;
console.log(a, b); // 5 10
}
console.log(a); // 5
}
show(5);Давайте разберём, что происходит при вызове show(5):
- Условие
n > 0истинно, и выполнение входит в веткуif. var a = nкладёт вaчисло5, аlet b = n * 2кладёт вbчисло10.- Внутри ветки видны обе переменные, и программа печатает
5 10. - После закрывающей скобки ветки
console.log(a)печатает5: переменнаяaпережила ветку.
Если поставить console.log(b) на место последней строки функции, программа остановится с ошибкой ReferenceError: b is not defined. Переменная a объявлена словом var, а b — словом let, и правила видимости у них разные.
Блок и область видимости
Область видимости — часть программы, в которой имя переменной можно прочитать. Блок — код в фигурных скобках: ветка if, тело цикла или функции. В нашей картинке блок — это комната со стеклянными стенами.
Фигурные скобки можно написать и отдельно, без if и for. Такая пара тоже считается блоком.
let и const живут в блоке
Переменная, объявленная через let или const, видна от строки объявления до закрывающей скобки своего блока:
- во вложенных блоках она видна, как коридор из комнаты;
- снаружи блока её нет;
- на закрывающей скобке блока она исчезает.
Поэтому в двух соседних блоках могут жить две разные переменные с одним именем:
const limit = 10;
{
const half = limit / 2;
if (half > 2) {
console.log(half); // 5
}
}
{
const half = 1;
console.log(half); // 1
}Разберём, кто что видит:
- Константа
limitобъявлена вне блоков, поэтому её видно в обоих. - Первая
halfвидна в своём блоке и во вложенном блокеif, и программа печатает5. - На первой закрывающей скобке первая
halfисчезает. - Вторая
half— уже другая константа, и программа печатает1.
Здесь картинка с комнатами перестаёт работать. Настоящая комната стоит и тогда, когда в ней никого нет. А блок создаётся заново каждый раз, когда выполнение входит в него, и пропадает вместе со своими переменными на закрывающей скобке.
var живёт в функции
Слово var — старый способ объявлять переменные, и такая переменная не замечает блоков. Её видно во всей функции, где она объявлена, даже после if или цикла. Такую область называют областью видимости функции.
Если функция — квартира, то переменная var стоит не в комнате, а в прихожей: её видно из любой комнаты этой квартиры. Параметры живут по тому же правилу: они видны во всём теле своей функции.
function lastSquare(n) {
for (var i = 1; i <= n; i++) {
var square = i * i;
}
return i + " " + square;
}
console.log(lastSquare(3)); // 4 9Давайте посмотрим, откуда берётся 4 9:
- Цикл проходит
iот1до3, и на последнем шагеsquareполучает9. - Затем
i++делаетiравной4, условиеi <= nстановится ложным, и цикл заканчивается. - Обе переменные пережили цикл, поэтому
returnсобирает строку4 9.
Если заменить оба var на let, строка с return остановит программу с ReferenceError. За пределы функции var не выходит: вне lastSquare имён i и square нет.
Этот вопрос часто задают на собеседовании: «Чем отличаются var, let и const?» Ответ состоит из трёх частей:
varвиден во всей функции и не замечает блоков;letиconstвидны только в своём блоке;- переменной
constнельзя присвоить новое значение.
В новом коде пишут let и const. var встречается в старом коде, и такой код нужно уметь читать.
Частая ошибка
Переменную объявили внутри веток if, а прочитали после них:
function label(n) {
if (n > 0) {
let sign = "plus";
} else {
let sign = "minus";
}
return sign; // ✗
}
console.log(label(5));ReferenceError: sign is not definedКаждая sign живёт только в своей ветке, и к строке с return обе уже исчезли. Чтобы прочитать переменную после if, объявите её до if строкой let sign;, а в ветках присвойте ей значение: sign = "plus"; и sign = "minus";.
Главное
- Область видимости — часть программы, где имя переменной можно прочитать.
letиconstвидны от своей строки до закрывающей скобки блока, включая вложенные блоки.varне замечает блоков и виден во всей функции, но не за её пределами.- Переменную, нужную после
if, объявляют доif, а в ветках только присваивают.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.