Статические члены класса в JavaScript
Статические свойства и методы JavaScript: ключевое слово static, наследование в подклассах, фабричные методы, блоки статической инициализации и поведение this.
Статические свойства и методы принадлежат самому классу, а не экземплярам, созданным на его основе. Это означает, что вы вызываете их напрямую через имя класса — без использования new. Они являются подходящим инструментом для вспомогательных функций и общих констант, относящихся к классу в целом, а не к отдельному объекту.
Если вы уже работали со встроенными объектами JavaScript, вы использовали статические члены, не называя их так:
Date.now()возвращает текущую временную метку — вызывается наDate, а не на экземпляре даты.Array.from(iterable)создаёт array — вызывается на классеArray, а не на существующем array.Object.keys(obj)возвращает список собственных ключей object — вызывается наObject.Math.max(...)иNumber.isInteger(...)тоже статические.
В этой главе объясняется, как определять собственные статические свойства и методы, как они наследуются подклассами, как ведёт себя this внутри них, а также рассматриваются распространённые паттерны (фабричные методы и блоки статической инициализации), которые вы будете применять в реальном коде. Если классы для вас — новая тема, начните с базового синтаксиса классов.
Определение статических свойств и методов
Статические свойства и методы определяются с помощью ключевого слова static внутри тела класса. Вот как их определять и использовать:
В этом примере pi — статическое свойство, а sum — статический метод класса Calculator. К ним можно обратиться напрямую через имя класса без его инстанцирования.
Примечание: синтаксис статических полей класса (static pi = ...) требует ES2022+ или транспилятора наподобие Babel. Кроме того, статический метод не может обратиться к свойствам экземпляра через this, поскольку он принадлежит самому классу, а не какому-либо конкретному экземпляру.
this внутри статического метода
Внутри статического метода this ссылается на класс, а не на экземпляр. Это позволяет одному статическому методу вызывать другой статический метод или читать статическое свойство того же класса:
Поскольку this разрешается в класс, один и тот же статический метод ведёт себя по-разному в зависимости от того, через какой класс он был вызван — это важная деталь, когда в игру вступает наследование (см. следующий раздел).
Наследование статических членов в подклассах
Статические свойства и методы наследуются. Когда подкласс расширяет (extends) родительский класс, он получает доступ к статическим членам родителя и может вызывать их через своё имя:
Здесь Advanced.sum унаследован от Calculator. Внутри Advanced.double значение this — это Advanced, поэтому this.sum(...) находит sum вверх по цепочке прототипов.
Поскольку this указывает на класс, через который был вызван метод, подкласс может переопределить статический член, и другие статические методы родителя будут использовать переопределённую версию при вызове через подкласс:
Подробнее о расширении классов см. в разделе наследование классов.
Статические фабричные методы
Распространённый паттерн — фабричный метод: статический метод, который создаёт и возвращает экземпляр класса, зачастую из данных иной формы. Это позволяет сосредоточить логику конструирования в одном именованном месте и сделать вызывающий код читаемым.
Типичный пример — создание object из JSON-строки или обычного object, полученного от API:
Использование new this(...) вместо new User(...) означает, что подкласс, вызывающий fromJSON, автоматически получает экземпляр подкласса.
Когда использовать статические свойства
Статические свойства идеально подходят для констант, связанных с классом, которые не меняются независимо от экземпляра класса. Они предоставляют способ обращаться к общим данным из любой части кода. Например, если у вас есть класс, работающий с пользовательскими взаимодействиями, вы можете задать статическое свойство с настройками по умолчанию или ограничениями:
Для констант, которые не должны переназначаться извне класса, рассмотрите сочетание статических полей с приватными членами (static #secret = ...).
Блоки статической инициализации
Иногда для инициализации статического свойства недостаточно одного выражения — например, оно зависит от нескольких других статических свойств, требует цикла или блока try/catch. В ES2022 были добавлены блоки статической инициализации (static { ... }) именно для таких случаев. Блок выполняется один раз — при определении класса — и this привязан к классу:
Допускается несколько статических блоков — они выполняются в порядке следования в исходном коде, чередуясь с инициализаторами статических полей. Они идеально подходят для вычисляемой настройки, которую неудобно выражать в виде одного присваивания поля.
Преимущества использования статических свойств и методов
- Эффективность памяти: поскольку статические свойства и методы привязаны к самому классу, а не к экземплярам, они не дублируют данные или функции для каждого object, что позволяет снизить накладные расходы на память при создании большого числа экземпляров.
- Удобство: статические методы можно вызывать без инстанцирования класса, что делает их удобными для вспомогательных функций.
- Организованность кода: группировка связанной функциональности непосредственно в классах в виде статических членов позволяет поддерживать порядок в коде и чётко определять функциональные области.
Итоги
- Статические члены объявляются с ключевым словом
staticи находятся в классе, а не в экземплярах — обращайтесь к ним какИмяКласса.член. - Хорошо знакомые встроенные методы, такие как
Date.now(),Array.from()иObject.keys(), являются статическими. - Внутри статического метода
this— это класс, через который он был вызван. Подклассы наследуют статические члены, могут их переопределять, иthisразрешается соответственно. - Используйте фабричные методы (
static fromJSON(...), возвращающийnew this(...)) для централизации создания объектов, и блоки статической инициализации (static { ... }, ES2022) для настройки, требующей более одного выражения. - Применяйте статические члены для вспомогательных функций и общих констант; используйте обычные (экземплярные) методы для поведения, зависящего от данных конкретного object.
Дальнейшие шаги
- Базовый синтаксис классов — основы
class, конструкторов и методов экземпляра. - Наследование классов — как работают
extendsиsuper, в том числе со статическими членами. - Приватные и защищённые свойства и методы — сочетание
#privateсоstaticдля защиты данных на уровне класса.