Глобальная область видимости в JavaScript
- среда, 11 февраля 2026 г. в 00:00:08
Как любой другой язык программирования, JavaScript позволяет создавать элементы доступные в любом месте приложения. И, как и с другими механизмами, JS тут имеет свои уникальные, но важные особенности, которые мы подробно рассмотрим.
Глобальная область видимости может принимать различные формы в зависимости от того как загружаются код JS:
Модулей ES6. Когда файлы с модулями загружаются по отдельности, каждый загруженный модуль, импортирует другие модули. Файлы модулей взаимодействуют через директиву import, без обращений к глобальной области видимости;
Использования сборщика, собирающего единый бандл из множества файлов. Сборщики упаковывают содержимое файлов в единую область видимости (UMD - Universal Module Definition), которая представляет собой функцию обёртку:
(function(root, factory) { // Проверка на среду Node.js или браузер if (typeof exports === 'object' && typeof module !== 'undefined') { module.exports = factory() } else { root.myModule = factory() } }(typeof self !== 'undefined' ? self : this, function() { return { // Ваш код greeting: function() { return 'Привет Васятка!' } } }))
Внутри данной области видимости, создаются глобальные для всего приложения переменные, при помощи которых различные части программы, общаются между собой. Таким образом создаётся единая для всего приложения область видимости, которая технически является функциональной, а не глобальной;
3. Подключение файлов по отдельности через тег <script/>. При таком подходе каждая переменная объявленная на верхнем уровне (вне функции или блока), любого из файлов становится глобальной.
Через глобальную область видимости предоставляется доступ к:
Примитивам:
undefinde;
null;
Infinity;
Nan.
Стандартным объектам (Date(), Object(), String() и т.д.);
Стандартным функциям (eval(), parseInt() и т.д.);
Стандартным API:
Math;
Atomics;
JSON.
Дополнительным средствам:
Intl;
WebAssembly.
В зависимости от того в какой среде выполняется код, глобальная область видимости, может предоставлять к специфичным для этой среды фичам:
Консоли и её методам;
Средствам для работы с DOM (window, document и т.д.);
Информации об ОС и процессе запустившим код;
API веб-платформы (navigator, history, геолокация, WebRTC и т.д.).
То есть вместо:
let now = new Date()
Можно написать:
let now = new window.Date()
И всё будет работать тождественно.
Глобальная область видимости должна использоваться умеренно, не превращаясь в свалку для переменных. В первую очередь она должна быть связующей средой, для частей приложения. В программировании вообще считается хорошим тоном, сведение использования глобальных зависимостей к минимуму.
Все переменные объявленные при помощи var и функции становятся свойствами и методами глобального объекта window (о чём в скользь говорилось в предыдущей статье о всплытии переменных):
var greeting = 'Привет мир! Это Васятка!' console.log(greeting) // Привет мир! Это Васятка! console.log(window.greeting) // Привет мир! Это Васятка!
let и const такого эффекта не дают:
let greeting = 'Привет мир! Это Васятка!' console.log(greeting) // Привет мир! Это Васятка! console.log(window.greeting) // undefined
Чтобы избежать разночтений, для глобальных переменных следует использовать var, а для блоковых let или const.
Свойство глобального объекта window, может быть затенено глобальной переменной с таким-же именем:
console.log(window.innerWidth) // 1920 var innerWidth = 500 console.log(innerWidth) // 500 console.log(window.innerWidth) // Тоже 500. Оригинальное значение было затенено
Затенение может стать причиной сложнодиагностируемых багов. В примере выше мы изменили значение ширины окна во всем приложении, хотя у пользователя размер экрана остался прежним.
У глобального объекта window, есть заранее определённое свойство name. Его можно затенить если создать переменную через var, с таким-же именем. Так как name это заранее определённое get/set-свойство объекта window, которое настроено так что может быть только строкой и даже если присвоить ей число, оно будет преобразовано в строку:
var name = 42 console.log(name) // 42 console.log(typeof name) // string
В воркерах глобальная область видимости достаточно чистая, ведь они выполняются во второстепенном потоке, без доступа к DOM, а следовательно не имеют глобальных объектов для работы со всем этим хозяйством:
console.log(document) // Uncaught ReferenceError: document is not defined
Обращение к глобальной области видимости тут происходит через ключевое слово self. Как и в обычных программах var и function, создают свойства в глобальном объекте воркера:
var userName = 'Васятка' console.log(self.userName) // Васятка
а let и const нет:
let userName = 'Васятка' console.log(self.userName) // undefined
Переменные созданные в модуле через var или функции, не влияют на глобальную область видимости приложения, оставаясь глобальными только на уровне модуля. У модуля вообще нет аналога глобального объекта window. Они по минимуму зависят от глобальной области видимости, явно импортируя все необходимые для своей работы зависимости. И это хорошо!
В Node.js каждый подключаемый файл это отдельный модуль и глобальная области видимости, тут не играет такой-же большой роли, как в браузерном JavaScript. Node упаковывает свой код в функции-обёртки, подключая глобальные функции (например requer()) через аргументы. Под капотом Ваш модуль выглядит так:
(function(exports, require, module, __filename, __dirname) { // Код модуля })
Это легко можно проверить:
console.log(arguments.callee.toString()) /* Вывод: function (exports, require, module, __filename, __dirname) { console.log(arguments.length) console.log(arguments.callee.toString()) } */ console.log(arguments.length) // 5 аргументов: exports, require, module, __filename, __dirname
Объявить глобальную переменную в Node можно только при помощи объекта global являющегося аналогом window в браузерной версии:
const greeting = require('./greeting.js') global.userName = 'Васятка' greeting()
Потом применим её в модуле:
module.exports = function() { console.log(`Привет ${global.userName}!`) // Привет Васятка! }
global не является частью спецификации ES и есть только в Node.js.
Напоминаю что за использование eval() в проде, в аду положен отдельный котёл и полный спектр анальных утех без лубриканта, но всё-же разберёмся, как тут работает глобальная область видимости. Код внутри eval() видит глобальные переменные:
var userName = 'Васятка' eval('function greeting() {console.log(`Привет ${userName}!`)}; greeting()') // Привет Васятка!
И может их менять:
var userName = 'Васятка' eval('userName = "Пётр"') function greeting() { console.log(`Привет ${userName}!`) // Привет Пётр! } greeting()
Но при этом слава богу, сам eval() не может порождать глобальных переменных:
eval('var userName = "Васятка"') function greeting() { console.log(`Привет ${userName}!`) // Uncaught ReferenceError: userName is not defined } greeting()
globalThis - появился в ES2020 и является стандартизированной ссылкой на глобальную область видимости во всех средах JavaScript. Необходимость в подобном элементе возникла в связи с тем что в разных средах выполнения JS, ссылка на глобальную область видимости хранится в объектах:
window - в браузерах;
global - Node.js;
self - в воркерах;
globalThis устраняет эту фрагментацию и даёт простой и предсказуемый доступ к глобальному объекту, вне зависимости от среды. globalThis просто хранит ссылку на глобальный объект среды:
console.log(globalThis === window) // true
При работе с глобальной областью видимости, всегда стоит использовать globalThis. Это обезопасить код от ошибок, если он будет запущен в другой среде выполнения. Данное правило становится аксиомой, при разработке кроссплатформенных библиотек JavaScript.
Как и в любом другом языке, в JavaScript глобальные сущности это необходимое зло, от которого код должен завесить по минимуму. Современный JS, сам активно способствует этому инкапсулирую код в модулях ES6. Глобальная область видимости в JavaScript, обладает рядом неочевидных и уникальных особенностей, способных привести к проблемам в самых неожиданных местах. В этой статье, я подробно описал нюансы работы глобальной области видимости JS. Надеюсь кому-то она поможет избежать сложных багов или поразить глубиной преисполненности, лида во время собеса.