--- title: Поля классов slug: Web/JavaScript/Reference/Classes/Public_class_fields tags: - JavaScript - Классы translation_of: Web/JavaScript/Reference/Classes/Public_class_fields original_slug: Web/JavaScript/Reference/Classes/Class_fields ---
И статические, и публичные поля являются изменяемыми, перечисляемыми, настраиваемыми свойствами. Таким образом, в отличие от приватных полей, они участвуют в прототипном наследовании.
Публичные статические поля полезны тогда, когда необходимо существование одного единственного поля для всего класса, а не для каждого созданного экземпляра по отдельности. Это полезно для кеша, конфигураций или любых прочих данных, которые одинаковы для всех экземпляров.
Публичные статические поля объявляются при помощи ключевого слова static
. Они добавляются в конструктор класса во время его создания с помощью Object.defineProperty. Доступ также осуществляется через конструктор класса.
class ClassWithStaticField { static staticField = 'static field'; } console.log(ClassWithStaticField.staticField); // Ожидаемый вывод: "static field"
Поля без инициализации имеют значение undefined
.
class ClassWithStaticField { static staticField; } console.assert(ClassWithStaticField.hasOwnProperty('staticField')); console.log(ClassWithStaticField.staticField); // Ожидаемый вывод: "undefined"
Публичные статические поля не переопределяются в наследниках класса, а могут быть доступны через иерархию прототипов.
class ClassWithStaticField { static baseStaticField = 'base field'; } class SubClassWithStaticField extends ClassWithStaticField { static subStaticField = 'sub class field'; } console.log(SubClassWithStaticField.subStaticField); // Ожидаемый вывод: "sub class field" console.log(SubClassWithStaticField.baseStaticField); // Ожидаемый вывод: "base field"
При определении полей this
ссылается на конструктор класса. Также можно обратиться к нему по имени и использовать super
для получения конструктора базового класса, если он существует.
class ClassWithStaticField { static baseStaticField = 'base static field'; static anotherBaseStaticField = this.baseStaticField; static baseStaticMethod() { return 'base static method output'; } } class SubClassWithStaticField extends ClassWithStaticField { static subStaticField = super.baseStaticMethod(); } console.log(ClassWithStaticField.anotherBaseStaticField); // Ожидаемый вывод: "base static field" console.log(SubClassWithStaticField.subStaticField); // Ожидаемый вывод: "base static method output"
Такие публичные поля имеются у каждого экземпляра данного класса. Объявляя публичные поля, мы можем гарантировать, что поле всегда актуально, а объявление класса является более самодокументированным.
Публичные поля экземпляра добавляются через Object.defineProperty либо перед тем, как будет исполнено тело конструктора в базовом классе, либо после того, как завершится super()
в классе наследнике.
class ClassWithInstanceField { instanceField = 'instance field'; } const instance = new ClassWithInstanceField(); console.log(instance.instanceField); // Ожидаемый вывод: "instance field"
Поля без инициализации имеют значение undefined
.
class ClassWithInstanceField { instanceField; } const instance = new ClassWithInstanceField(); console.assert(instance.hasOwnProperty('instanceField')); console.log(instance.instanceField); // Ожидаемый вывод: "undefined"
Как и свойства, названия полей могут вычисляться.
const PREFIX = 'prefix'; class ClassWithComputedFieldName { [`${PREFIX}Field`] = 'prefixed field'; } const instance = new ClassWithComputedFieldName(); console.log(instance.prefixField); // Ожидаемый вывод: "prefixed field"
При определении полей this
ссылается на создающийся экземпляр класса. Как и в публичных методах экземпляра, получить доступ к прототипу базового класса можно с помощью super
.
class ClassWithInstanceField { baseInstanceField = 'base field'; anotherBaseInstanceField = this.baseInstanceField; baseInstanceMethod() { return 'base method output'; } } class SubClassWithInstanceField extends ClassWithInstanceField { subInstanceField = super.baseInstanceMethod(); } const base = new ClassWithInstanceField(); const sub = new SubClassWithInstanceField(); console.log(base.anotherBaseInstanceField); // Ожидаемый вывод: "base field" console.log(sub.subInstanceField); // Ожидаемый вывод: "base method output"
Ключевое слово static
объявляет статический метод класса. Статические методы не вызываются из экземпляра, вместо этого они вызывается из самого класса. Чаще всего это какие-либо служебные функции, такие как функции создания или копирования объектов.
{{EmbedInteractiveExample("pages/js/classes-static.html")}}
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
Статические методы добавляются в конструктор класса с помощью Object.defineProperty во время его создания. Эти методы - изменяемые, неперечисляемые и настраиваемые свойства объекта.
Как и следует из названия, публичные методы экземпляра это методы, доступные для вызова из экземпляров.
class ClassWithPublicInstanceMethod { publicMethod() { return 'hello world'; } } const instance = new ClassWithPublicInstanceMethod(); console.log(instance.publicMethod()); // Ожидаемый вывод: "hello world"
Публичные методы добавляются в прототип класса во время его создания с помощью Object.defineProperty. Они изменяемы, неперечисляемы и настраиваемы.
Вы можете использовать генераторы, асинхронные функции и асинхронные генераторы.
class ClassWithFancyMethods { *generatorMethod() { } async asyncMethod() { } async *asyncGeneratorMethod() { } }
Внутри методов экземпляра, this
ссылается на сам экземпляр.
В классах наследниках, super
дает доступ к прототипу базового класса, позволяя вызывать его методы.
class BaseClass { msg = 'hello world'; basePublicMethod() { return this.msg; } } class SubClass extends BaseClass { subPublicMethod() { return super.basePublicMethod(); } } const instance = new SubClass(); console.log(instance.subPublicMethod()); // Ожидаемый вывод: "hello world"
Геттеры и сеттеры это специальные методы, которые привязаны к свойствам класса и которые вызываются, когда к свойству обращаются или записывают. Используйте get и set для объявления публичных геттеров и сеттеров экземпляра.
class ClassWithGetSet { #msg = 'hello world'; get msg() { return this.#msg; } set msg(x) { this.#msg = `hello ${x}`; } } const instance = new ClassWithGetSet(); console.log(instance.msg); // Ожидаемый вывод: "hello world" instance.msg = 'cake'; console.log(instance.msg); // Ожидаемый вывод: "hello cake"
Приватные поля доступны через конструктор внутри объявления самого класса.
Также сохраняется ограничение на вызов статических полей только внутри статических методов.
class ClassWithPrivateStaticField { static #PRIVATE_STATIC_FIELD; static publicStaticMethod() { ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42; return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD; } } assert(ClassWithPrivateStaticField.publicStaticMethod() === 42);
Приватные статические поля добавляются в конструктор на этапе оценки класса.
Существует ограничение происхождения приватных статических полей. Только класс, который объявляет приватное статическое поле, может обращаться к нему. Это может привести к неожиданному поведению при использовании this
.
class BaseClassWithPrivateStaticField { static #PRIVATE_STATIC_FIELD; static basePublicStaticMethod() { this.#PRIVATE_STATIC_FIELD = 42; return this.#PRIVATE_STATIC_FIELD; } } class SubClass extends BaseClassWithPrivateStaticField { } assertThrows(() => SubClass.basePublicStaticMethod(), TypeError);
Приватные поля объекта объявляются как # names ( произносятся как "hash names"), которые являются идентификаторами с префиксом #. # является частью самого имени и также используется для объявления и доступа.
Инкапсуляция обеспечивается языком. Ссылка на # names вне области видимости является синтаксической ошибкой.
class ClassWithPrivateField { #privateField; constructor() { this.#privateField = 42; this.#randomField = 666; # Syntax error } } const instance = new ClassWithPrivateField(); instance.#privateField === 42; // Syntax error
Как и публичные методы, приватные статические методы вызываются в классе, а не в экземплярах класса. Как и приватные статические поля, они доступны только из объявления класса.
Приватные статические методы могут быть генераторами, асинхронными функциями и асинхронными генераторами.
class ClassWithPrivateStaticMethod { static #privateStaticMethod() { return 42; } static publicStaticMethod() { return ClassWithPrivateStaticMethod.#privateStaticMethod(); } } assert(ClassWithPrivateStaticField.publicStaticMethod() === 42);
Приватные методы экземпляра объекта являются методами, доступными в экземплярах класса чей доступ ограничен так же, как и приватные поля экземпляра объекта.
class ClassWithPrivateMethod { #privateMethod() { return 'hello world'; } getPrivateMessage() { return #privateMethod(); } } const instance = new ClassWithPrivateMethod(); console.log(instance.getPrivateMessage()); // expected output: "hello world"
Приватные методы экземпляра объекта могут быть генераторами, асинхронными функциями и асинхронными генераторами. Также возможны приватные геттеры и сеттеры:
class ClassWithPrivateAccessor { #message; get #decoratedMessage() { return `✨${this.#message}✨`; } set #decoratedMessage(msg) { this.#message = msg; } constructor() { this.#decoratedMessage = 'hello world'; console.log(this.#decoratedMessage); } } new ClassWithPrivateAccessor(); // expected output: "✨hello world✨"
{{Compat("javascript.classes.public_class_fields")}}
{{Compat("javascript.classes.private_class_fields")}}