Классы
Базовый Широко доступен
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с марта 2016 года.
Классы — это шаблон для создания объектов. Они инкапсулируют данные с кодом, который работает с этими данными. Классы в JS построены на основе прототипов, но также имеют некоторый синтаксис и семантику, уникальные для классов.
Дополнительные примеры и объяснения см. в руководстве Использование классов.
Описание
Определение классов
Классы на самом деле являются «специальными функциями», и так же, как вы можете определять выражения функций и объявления функций, класс можно определить двумя способами: выражение класса или объявление класса.
// Declaration
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
// Expression; the class is anonymous but assigned to a variable
const Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
// Expression; the class has its own name
const Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
Как и выражения функций, выражения классов могут быть анонимными или иметь имя, отличное от имени переменной, которой они присвоены. Однако, в отличие от объявлений функций, объявления классов имеют те же ограничения временной мертвой зоны (TDZ), что и let или const, и ведут себя так, как будто они не поднимаются.
Тело класса
Тело класса — это часть, заключенная в фигурные скобки {}. Здесь вы определяете члены класса, такие как методы или конструктор.
Тело класса выполняется в строгом режиме, даже без директивы "use strict".
Элемент класса может быть охарактеризован тремя аспектами:
- Тип: Геттер, сеттер, метод или поле
- Расположение: Статический или экземпляр
- Видимость: Публичный или приватный
Вместе они дают 16 возможных комбинаций. Чтобы разделить справку более логично и избежать пересечения контента, различные элементы подробно представлены на разных страницах:
- Определения методов
- Публичный метод экземпляра
- Геттер
- Публичный геттер экземпляра
- Сеттер
- Публичный сеттер экземпляра
- Публичные поля класса
- Публичное поле экземпляра
-
static - Публичный статический метод, геттер, сеттер и поле
- Приватные элементы
- Все, что является приватным
Примечание: Приватные элементы имеют ограничение, заключающееся в том, что все приватные имена, объявленные в одном классе, должны быть уникальными. Все остальные публичные свойства не имеют такого ограничения — вы можете иметь несколько публичных свойств с одинаковым именем, и последнее перезаписывает другие. Такое же поведение, как и в инициализаторах объектов.
Кроме того, существуют два специальных синтаксиса элементов класса: constructor и блоки статической инициализации, каждый со своими ссылками.
Конструктор
Метод constructor — это специальный метод для создания и инициализации объекта, созданного с помощью класса. В классе может быть только один специальный метод с именем "constructor" — будет выброшено SyntaxError, если класс содержит более одного вхождения метода constructor.
Конструктор может использовать ключевое слово super для вызова конструктора суперкласса.
Вы можете создавать свойства экземпляра внутри конструктора:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
В качестве альтернативы, если значения ваших свойств экземпляра не зависят от аргументов конструктора, вы можете определить их как поля класса.
Блоки статической инициализации
Блоки статической инициализации позволяют гибко инициализировать статические свойства, включая выполнение инструкций во время инициализации, предоставляя доступ к приватной области.
Может быть объявлено несколько статических блоков, и они могут чередоваться с объявлением статических полей и методов (все статические элементы оцениваются в порядке объявления).
Методы
Методы определяются в прототипе каждого экземпляра класса и разделяются всеми экземплярами. Методы могут быть обычными функциями, асинхронными функциями, генераторами или асинхронными генераторами. Дополнительную информацию см. в разделе определения методов.
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea();
}
// Method
calcArea() {
return this.height * this.width;
}
*getSides() {
yield this.height;
yield this.width;
yield this.height;
yield this.width;
}
}
const square = new Rectangle(10, 10);
console.log(square.area); // 100
console.log([...square.getSides()]); // [10, 10, 10, 10]
Статические методы и поля
Ключевое слово static определяет статический метод или поле для класса. Статические свойства (поля и методы) определяются в самом классе, а не в каждом экземпляре. Статические методы часто используются для создания утилитарных функций для приложения, в то время как статические поля полезны для кэшей, фиксированных конфигураций или любых других данных, которые не нужно реплицировать между экземплярами.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static displayName = "Point";
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.displayName; // undefined
p1.distance; // undefined
p2.displayName; // undefined
p2.distance; // undefined
console.log(Point.displayName); // "Point"
console.log(Point.distance(p1, p2)); // 7.0710678118654755
Объявления полей
С помощью синтаксиса объявления полей класса пример конструктора можно записать так:
class Rectangle {
height = 0;
width;
constructor(height, width) {
this.height = height;
this.width = width;
}
}
Поля класса похожи на свойства объектов, а не на переменные, поэтому мы не используем такие ключевые слова, как const для их объявления. В JavaScript приватные элементы используют специальный синтаксис идентификатора, поэтому модификаторы, такие как public и private, также не следует использовать.
Как показано выше, поля могут быть объявлены с начальным значением или без него. Поля без начальных значений по умолчанию равны undefined. Объявляя поля заранее, определения классов становятся более самодокументируемыми, а поля всегда присутствуют, что помогает оптимизации.
Дополнительную информацию см. в разделе публичные поля класса.
Приватные элементы
Используя приватные поля, определение можно уточнить следующим образом.
class Rectangle {
#height = 0;
#width;
constructor(height, width) {
this.#height = height;
this.#width = width;
}
}
Обращение к приватным полям извне класса является ошибкой; они могут быть прочитаны или записаны только внутри тела класса. Определяя элементы, которые невидимы вне класса, вы гарантируете, что пользователи ваших классов не смогут зависеть от внутренних деталей, которые могут меняться от версии к версии.
Приватные поля могут быть объявлены только заранее в объявлении поля. Они не могут быть созданы позже путем присваивания им, как это могут сделать обычные свойства.
Приватные методы и сеттеры также могут быть определены с использованием того же синтаксиса, что и их публичные аналоги, но с идентификатором, начинающимся с #.
Дополнительную информацию см. в разделе приватные элементы.
Наследование
Ключевое слово extends используется в объявлениях классов или выражениях классов для создания класса как дочернего по отношению к другой функции-конструктору (классу или функции).
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(`${this.name} barks.`);
}
}
const d = new Dog("Mitzie");
d.speak(); // Mitzie barks.
Если в подклассе присутствует конструктор, он должен сначала вызвать super() перед использованием this. Ключевое слово super также может использоваться для вызова соответствующих методов суперкласса.
class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(`${this.name} roars.`);
}
}
const l = new Lion("Fuzzy");
l.speak();
// Fuzzy makes a noise.
// Fuzzy roars.
Порядок оценки
Когда объявление класса class или выражение класса class оценивается, его различные компоненты оцениваются в следующем порядке:
- Предложение
extends, если оно присутствует, сначала оценивается. Оно должно привести к допустимой функции-конструктору илиnull, иначе будет выброшенTypeError. - Метод
constructorизвлекается, заменяется реализацией по умолчанию, еслиconstructorотсутствует. Однако, поскольку определениеconstructorявляется лишь определением метода, этот шаг не наблюдается. - Ключи свойств элементов класса оцениваются в порядке объявления. Если ключ свойства вычисляемый, вычисляемое выражение оценивается, при этом значение
thisустанавливается равным значениюthis, окружающему класс (не самому классу). Значения свойств еще не оцениваются. - Методы и сеттеры устанавливаются в порядке объявления. Методы и сеттеры экземпляра устанавливаются в свойство
prototypeтекущего класса, а статические методы и сеттеры устанавливаются в сам класс. Приватные методы и сеттеры экземпляра сохраняются для последующей установки непосредственно в экземпляр. Этот шаг не наблюдается. - Класс теперь инициализирован с прототипом, указанным
extends, и реализацией, указаннойconstructor. Для всех вышеуказанных шагов, если при вычислении выражения делается попытка получить доступ к имени класса, выбрасываетсяReferenceError, потому что класс еще не инициализирован. - Значения элементов класса оцениваются в порядке объявления:
- Для каждого поля экземпляра (публичного или приватного) сохраняется его выражение инициализатора. Инициализатор оценивается при создании экземпляра, в начале конструктора (для базовых классов) или непосредственно перед возвратом вызова
super()(для производных классов). - Для каждого статического поля (публичного или приватного) его инициализатор оценивается с
this, установленным равным самому классу, и свойство создается в классе. -
Блоки статической инициализации оцениваются с
this, установленным равным самому классу.
- Для каждого поля экземпляра (публичного или приватного) сохраняется его выражение инициализатора. Инициализатор оценивается при создании экземпляра, в начале конструктора (для базовых классов) или непосредственно перед возвратом вызова
- Класс теперь полностью инициализирован и может использоваться как функция-конструктор.
О том, как создаются экземпляры, см. в справке по constructor.
Примеры
Привязка `this` к методам экземпляра и статическим методам
Когда статический или экземплярный метод вызывается без значения для this, например, путем присвоения метода переменной и последующего его вызова, значение this внутри метода будет undefined. Это поведение сохраняется, даже если директива "use strict" не присутствует, поскольку код внутри тела class всегда выполняется в строгом режиме.
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
const obj = new Animal();
obj.speak(); // the Animal object
const speak = obj.speak;
speak(); // undefined
Animal.eat(); // class Animal
const eat = Animal.eat;
eat(); // undefined
Если мы перепишем вышеизложенное, используя традиционный синтаксис функций в нестрогом режиме, то вызовы метода this автоматически привязываются к globalThis. В строгом режиме значение this остается undefined.
function Animal() {}
Animal.prototype.speak = function () {
return this;
};
Animal.eat = function () {
return this;
};
const obj = new Animal();
const speak = obj.speak;
speak(); // global object (in non–strict mode)
const eat = Animal.eat;
eat(); // global object (in non-strict mode)
Спецификации
Совместимость с браузерами
| Настольные компьютеры | Мобильные устройства | Сервер | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox для Android | Opera Android | Safari на iOS | Samsung Internet | WebView Android | WebView на iOS | Bun | Deno | Node.js | |
classes |
49
42–49Требуется строгий режим. |
13 |
45 |
36
29–36Требуется строгий режим. |
9 |
9
42–49Требуется строгий режим. |
45 |
36
29–36Требуется строгий режим. |
9 |
5.0
4.0–5.0Требуется строгий режим. |
42–49
42–49Требуется строгий режим. |
9 |
1.0.0 |
1.0 |
6.0.0 |
constructor |
49
42–49Требуется строгий режим. |
13 |
45 |
36
29–36Требуется строгий режим. |
9 |
9
42–49Требуется строгий режим. |
45 |
36
29–36Требуется строгий режим. |
9 |
5.0
4.0–5.0Требуется строгий режим. |
42–49
42–49Требуется строгий режим. |
9 |
1.0.0 |
1.0 |
6.0.0 |
extends |
49
42–49Требуется строгий режим. |
13 |
45 |
36
29–36Требуется строгий режим. |
9 |
9
42–49Требуется строгий режим. |
45 |
36
29–36Требуется строгий режим. |
9 |
5.0
4.0–5.0Требуется строгий режим. |
42–49
42–49Требуется строгий режим. |
9 |
1.0.0 |
1.0 |
6.0.0 |
private_class_fields |
74 |
79 |
90 |
62 |
14.1 |
74 |
90 |
53 |
14.5 |
11.0 |
74 |
14.5 |
1.0.0 |
1.0 |
12.0.0 |
private_class_fields_in |
91 |
91 |
90 |
77 |
15 |
91 |
90 |
64 |
15 |
16.0 |
91 |
15 |
1.0.0 |
1.9 |
16.4.0 |
private_class_methods |
84 |
84 |
90 |
70 |
15 |
84 |
90 |
60 |
15 |
14.0 |
84 |
15 |
1.0.0 |
1.0 |
14.6.0 |
public_class_fields |
72 |
79 |
69 |
60 |
16
14–14.1Не поддерживает публичные статические поля. См. ошибку 194095. |
72 |
79 |
51 |
16
14–14.5Не поддерживает публичные статические поля. См. ошибку 194095. |
11.0 |
72 |
16
14–14.5Не поддерживает публичные статические поля. См. ошибку 194095. |
1.0.0 |
1.0 |
12.0.0 |
static |
49
42–49Требуется строгий режим. |
13 |
45 |
36
29–36Требуется строгий режим. |
9 |
9
42–49Требуется строгий режим. |
45 |
36
29–36Требуется строгий режим. |
9 |
5.0
4.0–5.0Требуется строгий режим. |
42–49
42–49Требуется строгий режим. |
9 |
1.0.0 |
1.0 |
6.0.0 |
См. также
- Руководство "Использование классов"
classclassвыражение- Функции
- ES6 In Depth: Classes на hacks.mozilla.org (2015)
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes