constructor
Baseline Широко доступно
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с марта 2016 года.
Метод constructor — это специальный метод класса для создания и инициализации экземпляра объекта этого класса.
Примечание: На этой странице представлена синтаксис constructor. О свойстве constructor, которое есть у всех объектов, см. Object.prototype.constructor.
Попробуйте
class Polygon {
constructor() {
this.name = "Polygon";
}
}
const poly = new Polygon();
console.log(poly.name);
// Expected output: "Polygon"
Синтаксис
constructor() { /* … */ }
constructor(argument0) { /* … */ }
constructor(argument0, argument1) { /* … */ }
constructor(argument0, argument1, /* …, */ argumentN) { /* … */ }
Существуют некоторые дополнительные ограничения синтаксиса:
- Метод класса с именем
constructorне может быть геттером, сеттером, асинхронным или генератором. - Класс не может иметь более одного метода
constructor.
Описание
Конструктор позволяет выполнять любую пользовательскую инициализацию, которая должна быть выполнена до вызова любых других методов для экземпляра объекта.
class Person {
constructor(name) {
this.name = name;
}
introduce() {
console.log(`Hello, my name is ${this.name}`);
}
}
const otto = new Person("Otto");
otto.introduce(); // Hello, my name is Otto
Если вы не предоставите собственный конструктор, вам будет предоставлен конструктор по умолчанию. Если ваш класс является базовым классом, конструктор по умолчанию пуст:
constructor() {}
Если ваш класс является производным классом, конструктор по умолчанию вызывает конструктор родительского класса, передавая все предоставленные аргументы:
constructor(...args) {
super(...args);
}
Примечание: Отличие явного конструктора, подобного приведенному выше, от конструктора по умолчанию заключается в том, что последний фактически не вызывает итератор массива через оператор расширения.
Это позволяет коду, подобному этому, работать:
class ValidationError extends Error {
printCustomerMessage() {
return `Validation failed :-( (details: ${this.message})`;
}
}
try {
throw new ValidationError("Not a valid phone number");
} catch (error) {
if (error instanceof ValidationError) {
console.log(error.name); // This is Error instead of ValidationError!
console.log(error.printCustomerMessage());
} else {
console.log("Unknown error", error);
throw error;
}
}
Классу ValidationError не нужен явный конструктор, поскольку ему не требуется выполнять какую-либо пользовательскую инициализацию. Конструктор по умолчанию затем берет на себя инициализацию родительского Error из полученного аргумента.
Однако, если вы предоставите собственный конструктор, а ваш класс наследуется от некоторого родительского класса, вы должны явно вызвать конструктор родительского класса, используя super(). Например:
class ValidationError extends Error {
constructor(message) {
super(message); // call parent class constructor
this.name = "ValidationError";
this.code = "42";
}
printCustomerMessage() {
return `Validation failed :-( (details: ${this.message}, code: ${this.code})`;
}
}
try {
throw new ValidationError("Not a valid phone number");
} catch (error) {
if (error instanceof ValidationError) {
console.log(error.name); // Now this is ValidationError!
console.log(error.printCustomerMessage());
} else {
console.log("Unknown error", error);
throw error;
}
}
Использование new для класса проходит следующие шаги:
- (Если это производный класс) Выполняется тело
constructorдо вызоваsuper(). Эта часть не должна обращаться кthis, поскольку он еще не инициализирован. - (Если это производный класс) Выполняется вызов
super(), который инициализирует родительский класс через тот же процесс. - Инициализируются поля класса текущего класса.
- Выполняется тело
constructorпосле вызоваsuper()(или все тело, если это базовый класс).
В теле constructor вы можете получить доступ к создаваемому объекту через this и к классу, который вызывается с помощью new, через new.target. Обратите внимание, что методы (включая геттеры и сеттеры) и цепочка прототипов уже инициализированы для this до выполнения constructor, поэтому вы можете даже получить доступ к методам подкласса из конструктора суперкласса. Однако, если эти методы используют this, this еще не будет полностью инициализирован. Это означает, что чтение публичных полей производного класса приведет к undefined, а чтение приватных полей — к TypeError.
new (class C extends class B {
constructor() {
console.log(this.foo());
}
} {
#a = 1;
foo() {
return this.#a; // TypeError: Cannot read private member #a from an object whose class did not declare it
// It's not really because the class didn't declare it,
// but because the private field isn't initialized yet
// when the superclass constructor is running
}
})();
Метод constructor может возвращать значение. В то время как базовый класс может возвращать что угодно из своего конструктора, производный класс должен возвращать объект или undefined, иначе будет выброшена ошибка TypeError.
class ParentClass {
constructor() {
return 1;
}
}
console.log(new ParentClass()); // ParentClass {}
// The return value is ignored because it's not an object
// This is consistent with function constructors
class ChildClass extends ParentClass {
constructor() {
return 1;
}
}
console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined
Если конструктор родительского класса возвращает объект, этот объект будет использоваться в качестве значения this, на котором будут определены поля производного класса. Этот трюк называется "переопределением возвращаемого значения", что позволяет полям производного класса (включая приватные) определяться на несвязанных объектах.
constructor следует обычному синтаксису методов, поэтому параметры по умолчанию, остаточные параметры и т. д. могут быть использованы.
class Person {
constructor(name = "Anonymous") {
this.name = name;
}
introduce() {
console.log(`Hello, my name is ${this.name}`);
}
}
const person = new Person();
person.introduce(); // Hello, my name is Anonymous
Конструктор должен быть литеральным именем. Вычисляемые свойства не могут стать конструкторами.
class Foo {
// This is a computed property. It will not be picked up as a constructor.
["constructor"]() {
console.log("called");
this.a = 1;
}
}
const foo = new Foo(); // No log
console.log(foo); // Foo {}
foo.constructor(); // Logs "called"
console.log(foo); // Foo { a: 1 }
Асинхронные методы, методы-генераторы, аксессоры и поля класса запрещено вызывать constructor. Приватные имена не могут быть вызваны #constructor. Любой член с именем constructor должен быть обычным методом.
Примеры
Использование конструктора
Этот фрагмент кода взят из примера с классами (живая демонстрация).
class Square extends Polygon {
constructor(length) {
// Here, it calls the parent class' constructor with lengths
// provided for the Polygon's width and height
super(length, length);
// NOTE: In derived classes, `super()` must be called before you
// can use `this`. Leaving this out will cause a ReferenceError.
this.name = "Square";
}
get area() {
return this.height * this.width;
}
set area(value) {
this.height = value ** 0.5;
this.width = value ** 0.5;
}
}
Вызов super в конструкторе, привязанном к другому прототипу
super() вызывает конструктор, который является прототипом текущего класса. Если вы измените сам прототип текущего класса, super() вызовет конструктор, который является новым прототипом. Изменение прототипа свойства prototype текущего класса не влияет на то, какой конструктор вызовет super().
class Polygon {
constructor() {
this.name = "Polygon";
}
}
class Rectangle {
constructor() {
this.name = "Rectangle";
}
}
class Square extends Polygon {
constructor() {
super();
}
}
// Make Square extend Rectangle (which is a base class) instead of Polygon
Object.setPrototypeOf(Square, Rectangle);
const newInstance = new Square();
// newInstance is still an instance of Polygon, because we didn't
// change the prototype of Square.prototype, so the prototype chain
// of newInstance is still
// newInstance --> Square.prototype --> Polygon.prototype
console.log(newInstance instanceof Polygon); // true
console.log(newInstance instanceof Rectangle); // false
// However, because super() calls Rectangle as constructor, the name property
// of newInstance is initialized with the logic in Rectangle
console.log(newInstance.name); // Rectangle
Спецификации
Совместимость с браузерами
| Настольные компьютеры | Мобильные | Сервер | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
constructor |
49
42–49Требуется строгий режим. |
13 |
45 |
36
29–36Требуется строгий режим. |
9 |
49
42–49Требуется строгий режим. |
45 |
36
29–36Требуется строгий режим. |
9 |
5.0
4.0–5.0Требуется строгий режим. |
49
42–49Требуется строгий режим. |
9 |
1.0.0 |
1.0 |
6.0.0 |
См. также
- Руководство по использованию классов
- Классы
- Статические блоки инициализации
classsuper()Object.prototype.constructor
© 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/constructor