Область видимости в JavaScript global, function и block scope

Содержание

  1. 1.Область видимости в JavaScript: 3 уровня
  2. 2.Где живут переменные: global и local
    1. 2.1.Global Scope в браузере и на сервере
  3. 3.Function и Block: как не путать
    1. 3.1.Function scope на примере
    2. 3.2.Block scope на примере
  4. 4.Разница между var let const
    1. 4.1.Hoisting и TDZ в 2 правила
  5. 5.7 ошибок со Scope и вылеты в прод
  6. 6.Заключение
Нужна качественная верстка сайта?
Специалисты Ворк24 помогут!
Хотите работать на фрилансе, но не знаете с чего начать?
Регистрируйтесь на бирже Ворк24!

Типовая ситуация: код работал, но после правки начал вести себя странно. Переменная внезапно стала undefined, значение «утекло» наружу или перезаписалось в другом месте. Причина часто одна — неверно понятая видимость переменной и уровень, в котором она объявлена.

Этот материал полезен тем, кто:

  • пишет и проводит ревью javascript-кода;
  • готовит ТЗ для разработчиков;
  • принимает правки и оценивает риски изменений.

Понимание области видимости помогает быстрее находить баги, формулировать требования к коду и избегать скрытых ошибок, которые проявляются уже в продакшене.

По данным спецификации ECMAScript (TC39, 2026), новые окружения выполнения создаются для функций и блоков кода, а доступ к переменным определяется лексической структурой программы и цепочкой областей видимости. Это базовое правило объясняет, почему один и тот же идентификатор может вести себя по-разному в зависимости от места объявления и типа конструкции.

Область видимости в JavaScript: 3 уровня

Scope — это правило, которое определяет, где имя переменной доступно в коде. Проще: из каких строк программы к ней можно обратиться. Правильная область видимости снижает риск конфликтов имён, делает код предсказуемым.

Области видимости в JavaScript представлены тремя уровнями:

  • Global;
  • Function;
  • Block.

Они вложены друг в друга и работают по одной логике. Переменные видны внутри своего уровня и всех вложенных, но не наоборот. Это и есть базовое правило видимости.

Когда движок встречает имя переменной, он ищет его по цепочке. Сначала — текущий фрейм выполнения. Если не находит, поднимается выше, во внешний уровень. Подъём идёт по лексической структуре кода, а не по порядку выполнения. В конце цепочки всегда стоит глобальный контекст.

Из-за этого важно, где именно объявлены переменные. Одна и та же строка может работать или ломаться в зависимости от уровня объявления. Особенно это заметно во вложенных функциях.

Простой пример:
let total = 10;
 
function calc() {
  let add = 5;
  return total + add;
}

calc(); // 15

Здесь add доступна только внутри функции. total объявлена снаружи и читается из внутренней области. Это поведение лежит в основе замыкания — когда внутренняя функция использует значения из внешней области видимости.

💡 Если вы видите неожиданный ReferenceError или undefined, сначала проверьте уровень scope и способ объявления переменной.

Где живут переменные: global и local

Глобальная и локальная области определяют, кто и откуда может читать или менять данные. Ошибки здесь редко видны сразу. Они всплывают после правок, когда код разрастается.

Глобальные переменные доступны из любого места программы. Удобно для быстрого доступа, но опасно для поддержки. Любой участок кода может их изменить, иногда — случайно. В итоге появляются скрытые зависимости и баги, которые сложно отследить.

Global Scope в браузере и на сервере

В глобальной области всё, что объявлено вне функций и блоков. В браузере такие имена попадают в глобальный объект окна. На сервере, в Node-окружении, глобальный контекст устроен иначе, но суть та же: переменная живёт дольше, чем ожидаете.

Практический вывод простой. Не рассчитывайте, что глобальное имя «никто не тронет». В большом проекте это приводит к поломкам.

Для задач и ТЗ действует одно правило: никаких неявных глобальных переменных. Все данные передаются через параметры функций и возвращаемые значения. Поведение кода остаётся явным.

Мини-диалог из практики:

— Добавьте фичу, нужно сохранить состояние.
— Ок. Состояние передаём параметром. Глобальные переменные не используем. Текущие глобальные имена не трогаем.

Уточнения экономят время на приёмке, снижают риск побочных эффектов.

❗ Неявная глобальная переменная почти всегда = баг, который сложно воспроизвести.

Короткий чек-лист, как запретить глобальные побочки в задаче:

  • Не объявлять переменные без let, const или var;
  • Передавать данные через параметры функций;
  • Явно описывать допустимые глобальные значения в ТЗ;
  • Проверять правки на пересечение имён;
  • Считать любое новое глобальное имя ошибкой без согласования.

Function и Block: как не путать

В JavaScript область видимости задаётся тем, где именно объявлено имя. При вызове функции создаётся отдельный фрейм, в котором хранятся её переменные и параметры. Отсюда и путаница: функция и блок ведут себя по-разному.

Function scope на примере

Переменная, объявленная внутри Function, доступна во всей функции, независимо от вложенных блоков. Это и есть функциональная область видимости.

11.png

Здесь total видна и в if, и после него. Блок не создаёт отдельную область для var. Это часто удивляет, если ожидать поведение как в других языках.

Block scope на примере

Блок {} создаёт отдельную область видимости для let и const. Переменные живут только внутри блока и не «протекают» наружу.
22.png

То же самое касается for, try/catch и других блоков. Такой Block-подход делает код безопаснее и проще для чтения.

Типичный пример с циклом и обработчиками:
33.png

С var переменная одна на весь цикл. С let на каждой итерации создаётся своё значение.

📌 Правило: если переменная нужна только внутри if, for или try, объявляйте её через let или const внутри блока.

Как выбрать уровень объявления:

  1. Определите, где значение реально нужно.
  2. Если только внутри блока — используйте let или const.
  3. Если во всей функции — объявляйте в начале функции.
  4. Не поднимайте переменную выше, чем требуется по логике.

Разница между var let const

Различие между var, let и const заключается в области видимости и правилах работы с переменными. От этого зависит, будет ли код вести себя предсказуемо при правках и масштабировании.

  • var видна во всей функции. Она игнорирует блоки и допускает повторное объявление. Это источник тихих ошибок.
  • let ограничена блоком и защищает от случайных конфликтов имён.
  • const тоже блочная, но дополнительно запрещает переназначение значения

Коротко: var живёт по старым правилам, let и const — по современным. В рабочем коде это критично.

Ключевое слово Scope Переобъявление Переназначение
var Function Да Да
let Block Нет Да
const Block Нет Нет

Hoisting и TDZ в 2 правила

Первое правило — поднятие (hoisting). Объявления var поднимаются в начало функции. Значение при этом остаётся undefined.

console.log(a); // undefined
var a = 10;

Код не падает, но работает не так, как ожидают многие.

Второе правило — временная мёртвая зона (TDZ) для let и const. Переменная существует, но к ней нельзя обратиться до строки объявления.

console.log(b); // ReferenceError
let b = 10;

Ошибка возникает сразу. Это защищает код от неявных обращений к неинициализированным данным.

Практический вывод для ревью и ТЗ простой:

  • Запрещайте var в новом коде;
  • Используйте const, если значение не меняется;
  • Применяйте let, если требуется переназначение;
  • Считайте повторное объявление переменной ошибкой.

✅ Для большинства задач: const по умолчанию, let — если нужно переназначение, var — только в легаси-коде.

Такой подход делает код чище и снижает риск багов при доработках.

7 ошибок со Scope и вылеты в прод

1.jpg

Большинство проблем с Scope появляются не из-за сложных алгоритмов, а из-за мелких неточностей. Ниже — ошибки, которые ломают код после релиза.

  1. Неявные глобальные.
    Переменную используют без let или const. Она уходит в глобальную видимость и может быть перезаписана где угодно.
  2. Теневое объявление.
    Внутри блока или функции объявляют переменную с тем же именем. Внешнее значение скрывается, логика ломается без ошибок.
  3. var в цикле + асинхронный колбэк.
    Колбэки читают одно и то же значение. Ожидали разные — получили одинаковые.
  4. Ожидание scope от if для var.
    Блок if не создаёт область видимости для var. Переменная «выползает» наружу.

  1. Путаница с параметрами и внешними именами.
    Параметр функции совпадает по имени с внешней переменной. Читается неверное значение.
  2. Замыкание держит лишнее.
    Функция сохраняет ссылки на внешние данные дольше, чем нужно. Появляются косвенные утечки, неожиданные эффекты.
  3. Правка в одном месте ломает другое.
    Код зависит от внешнего контекста. Изменение кажется локальным, но влияет на весь JavaScript-файл.

❗ Если баг «то появляется, то исчезает», проверьте пересечения имён и глобальные состояния.

Чтобы такие ошибки не доходили до продакшена, их стоит фиксировать в требованиях. В ТЗ и критериях приёмки полезно явно указать:

  • Запрет на неявные глобальные переменные;
  • Использование let и const по умолчанию;
  • Отсутствие пересечений имён во внешних областях;
  • Обязательную проверку линтером перед сдачей.
Короткий шаблон согласования правки:

— Добавляем переменную для расчёта.
— Где она живёт? Глобально нельзя.
— Ок, объявляем внутри функции, без доступа снаружи.

Такой подход снижает риск скрытых ошибок и упрощает ревью.

Заключение

В JavaScript есть три уровня области видимости: глобальный, функции и блока. Ошибки начинаются там, где переменная объявлена выше, чем нужно, или живёт дольше, чем ожидается. Поэтому важно сразу понимать, в каком месте она должна существовать, кто имеет к ней доступ.

Чтобы снизить риск конфликтов и упростить чтение кода, используйте:

  • const — по умолчанию.
  • let — когда значение меняется.
  • var — только в старом коде, где его уже нельзя безопасно заменить.

При ревью и приёмке полезно делать быструю проверку. Посмотрите, нет ли неявных глобальных переменных. Убедитесь, что имена не пересекаются между внешними и внутренними областями. Проверьте циклы с асинхронными вызовами — закрадываются ошибки с областью видимости в JS.

Вам нужна биржа фриланса для новичков или требуются разработчики сайтов?

Комментарии

Нет комментариев
Не можешь разобраться в этой теме?
Обратись за помощью к фрилансерам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 1 дня
Безопасная сделка
Прямой эфир