Настройка глобальных переменных: globals

В JavaScript многие среды выполнения предоставляют заранее определённые глобальные объекты: window в браузере, process в Node.js, document, setTimeout, Buffer, require и десятки других. Для статического анализатора кода важно понимать, какие идентификаторы являются встроенными, а какие — ошибочными или потенциально неопределёнными. Именно для этого в ESLint существует механизм настройки глобальных переменных через globals.


Назначение механизма globals

ESLint по умолчанию анализирует код в строгом режиме: любое использование необъявленной переменной считается ошибкой (no-undef). Это поведение полезно для обнаружения опечаток и проблем области видимости, но становится некорректным, когда речь идёт о внешних окружениях или заранее известных глобальных объектах.

Механизм globals позволяет:

  • объявить переменные, существующие вне области модуля;
  • управлять их изменяемостью;
  • адаптировать линтер под конкретную среду выполнения;
  • снижать количество ложных срабатываний no-undef.

Базовая структура конфигурации globals

В конфигурации ESLint глобальные переменные задаются через объект:

{
  "globals": {
    "MyGlobalVar": "readonly",
    "debugMode": "writable",
    "window": "readonly"
  }
}

Каждое свойство объекта:

  • ключ — имя глобальной переменной;
  • значение — режим доступа.

Режимы доступа к глобальным переменным

readonly

Значение readonly указывает, что переменная существует, но её нельзя переопределять.

{
  "globals": {
    "process": "readonly"
  }
}

Любая попытка присваивания вызовет ошибку линтинга:

process = {}; // ошибка ESLint

Использование этого режима соответствует встроенным API среды выполнения, которые не предполагают изменения.


writable

Режим writable позволяет изменять значение глобальной переменной.

{
  "globals": {
    "DEBUG": "writable"
  }
}
DEBUG = true;

Такой подход используется для флагов конфигурации, polyfill-переменных или legacy-кода, где глобальные состояния изменяются динамически.


off

Значение off полностью отключает проверку существования переменной.

{
  "globals": {
    "legacyAPI": "off"
  }
}

Это означает, что ESLint не будет считать использование legacyAPI ошибкой, но также не будет контролировать её запись или чтение.


Глобальные переменные в разных окружениях

ESLint часто используется в проектах, работающих в различных средах. Каждая из них предоставляет свой набор глобальных объектов.

Браузерное окружение

В браузере доступны:

  • window
  • document
  • navigator
  • fetch
  • localStorage

Конфигурация:

{
  "globals": {
    "window": "readonly",
    "document": "readonly",
    "navigator": "readonly",
    "fetch": "readonly"
  }
}

Node.js окружение

Node.js добавляет свои глобальные сущности:

  • process
  • Buffer
  • require
  • __dirname
  • module

Пример настройки:

{
  "globals": {
    "process": "readonly",
    "Buffer": "readonly",
    "require": "readonly",
    "__dirname": "readonly",
    "__filename": "readonly"
  }
}

Тестовые среды

В тестовых рантаймах (например, Jest, Mocha) появляются дополнительные глобальные функции:

  • describe
  • it
  • test
  • beforeEach
  • afterEach
{
  "globals": {
    "describe": "readonly",
    "it": "readonly",
    "test": "readonly",
    "expect": "readonly"
  }
}

Встроенные пресеты globals через environment

Хотя globals можно задавать вручную, ESLint предоставляет более высокий уровень абстракции — env. При включении окружения ESLint автоматически добавляет соответствующие глобальные переменные.

{
  "env": {
    "browser": true,
    "node": true
  }
}

Это эквивалентно добавлению большого списка переменных в globals.

Однако globals остаётся актуальным, когда:

  • требуется точечная настройка;
  • необходимо объявить кастомные глобальные объекты;
  • нужно переопределить поведение стандартных глобалов.

Кастомные глобальные переменные

Во многих проектах используются глобальные объекты, добавленные сборщиком или runtime-системой.

Пример с webpack DefinePlugin

globalThis.APP_VERSION = "1.0.0";

ESLint конфигурация:

{
  "globals": {
    "APP_VERSION": "readonly"
  }
}

Пример с window-конфигурацией

window.CONFIG = {
  apiUrl: "https://api.example.com"
};
{
  "globals": {
    "CONFIG": "readonly"
  }
}

Глобальные переменные и строгий режим анализа

ESLint рассматривает каждое необъявленное имя как потенциальную ошибку:

console.log(apiKey);

Если apiKey не определён в globals, env или scope, возникает ошибка no-undef.

После добавления:

{
  "globals": {
    "apiKey": "readonly"
  }
}

код становится валидным с точки зрения линтера.


Взаимодействие globals с правилами ESLint

Настройка globals напрямую влияет на работу следующих правил:

  • no-undef — определяет, существует ли переменная;
  • no-global-assign — запрещает перезапись глобалов;
  • no-shadow — учитывает глобальные имена при проверке затенения;
  • no-redeclare — предотвращает повторное объявление.

Например:

{
  "globals": {
    "window": "readonly"
  }
}
var window = {}; // конфликт с глобальной переменной

Использование в flat config (ESLint 9+)

В новой системе конфигурации используется JavaScript-объект:

export default [
  {
    languageOptions: {
      globals: {
        process: "readonly",
        Buffer: "readonly",
        APP_MODE: "readonly"
      }
    }
  }
];

Здесь globals перемещён внутрь languageOptions, что отражает более структурированную модель конфигурации.


Автоматические и предопределённые глобалы

Некоторые среды автоматически включают глобальные переменные через плагины:

  • eslint-plugin-node
  • eslint-plugin-browser
  • eslint-plugin-jest

Эти плагины расширяют список доступных глобальных идентификаторов без ручной настройки.


Конфликты и типичные ошибки конфигурации

Ошибка: отсутствие глобальной переменной

fetch("/api");

Если fetch не объявлен в globals или env, ESLint выдаёт ошибку.


Ошибка: неправильный режим доступа

{
  "globals": {
    "CONFIG": "readonly"
  }
}
CONFIG = {}; // ошибка

Если проект требует изменения глобального объекта, необходимо использовать writable.


Ошибка: дублирование через env и globals

Одновременное объявление через env и globals может привести к путанице и конфликтам при расширении конфигураций, особенно при наследовании конфигов.


Наследование конфигураций globals

ESLint позволяет объединять конфигурации:

{
  "extends": ["eslint:recommended"],
  "globals": {
    "customGlobal": "readonly"
  }
}

При этом локальные настройки дополняют или переопределяют унаследованные глобальные переменные.


Практика организации globals в проектах

В крупных проектах глобальные переменные обычно структурируются по категориям:

  • системные (process, window);
  • сборочные (__DEV__, APP_VERSION);
  • интеграционные (Stripe, Analytics);
  • тестовые (jest, cy).

Разделение помогает избегать хаотичного накопления глобальных имен и снижает вероятность конфликтов.


Безопасность и контроль глобального пространства

Избыточное использование глобальных переменных усложняет анализ кода и увеличивает риск:

  • неявных зависимостей;
  • коллизий имён;
  • неконтролируемых побочных эффектов.

ESLint через globals выступает как слой документирования глобального пространства, фиксируя договорённости между инструментами сборки, средой выполнения и исходным кодом.