- constructor
- Try it
- Syntax
- Description
- Examples
- Using the constructor
- Calling super in a constructor bound to a different prototype
- Specifications
- Browser compatibility
- See also
- Конструктор объектов в JS
- Создание нескольких объектов с помощью одного конструктора
- Ключевое слово this в конструкторе
- Конструктор с параметрами
- Отличие простого объявления от конструктора
- Количество объектов
- Уникальность объектов
- Добавление свойств и методов в объект
- Встроенные конструкторы
- Как использовать
- Строки
- Числа
- Логические значения
constructor
The constructor method is a special method of a class for creating and initializing an object instance of that class.
Note: This page introduces the constructor syntax. For the constructor property present on all objects, see Object.prototype.constructor .
Try it
Syntax
constructor() /* … */ > constructor(argument0) /* … */ > constructor(argument0, argument1) /* … */ > constructor(argument0, argument1, /* … ,*/ argumentN) /* … */ >
There are some additional syntax restrictions:
- A class method called constructor cannot be a getter, setter, async, or generator.
- A class cannot have more than one constructor method.
Description
A constructor enables you to provide any custom initialization that must be done before any other methods can be called on an instantiated object.
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
If you don’t provide your own constructor, then a default constructor will be supplied for you. If your class is a base class, the default constructor is empty:
If your class is a derived class, the default constructor calls the parent constructor, passing along any arguments that were provided:
constructor(. args) super(. args); >
Note: The difference between an explicit constructor like the one above and the default constructor is that the latter doesn’t actually invoke the array iterator through argument spreading.
That enables code like this to work:
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; > >
The ValidationError class doesn’t need an explicit constructor, because it doesn’t need to do any custom initialization. The default constructor then takes care of initializing the parent Error from the argument it is given.
However, if you provide your own constructor, and your class derives from some parent class, then you must explicitly call the parent class constructor using super() . For example:
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; > >
Using new on a class goes through the following steps:
- (If it’s a derived class) The constructor body before the super() call is evaluated. This part should not access this because it’s not yet initialized.
- (If it’s a derived class) The super() call is evaluated, which initializes the parent class through the same process.
- The current class’s fields are initialized.
- The constructor body after the super() call (or the entire body, if it’s a base class) is evaluated.
Within the constructor body, you can access the object being created through this and access the class that is called with new through new.target . Note that methods (including getters and setters) and the prototype chain are already initialized on this before the constructor is executed, so you can even access methods of the subclass from the constructor of the superclass. However, if those methods use this , the this will not have been fully initialized yet. This means reading public fields of the derived class will result in undefined , while reading private fields will result in a 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 > >)();
The constructor method may have a return value. While the base class may return anything from its constructor, the derived class must return an object or undefined , or a TypeError will be thrown.
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
If the parent class constructor returns an object, that object will be used as the this value on which class fields of the derived class will be defined. This trick is called «return overriding», which allows a derived class’s fields (including private ones) to be defined on unrelated objects.
The constructor follows normal method syntax, so parameter default values, rest parameters, etc. can all be used.
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
The constructor must be a literal name. Computed properties cannot become constructors.
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
Async methods, generator methods, accessors, and class fields are forbidden from being called constructor . Private names cannot be called #constructor . Any member named constructor must be a plain method.
Examples
Using the constructor
This code snippet is taken from the classes sample (live demo).
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; > >
Calling super in a constructor bound to a different prototype
super() calls the constructor that’s the prototype of the current class. If you change the prototype of the current class itself, super() will call the constructor that’s the new prototype. Changing the prototype of the current class’s prototype property doesn’t affect which constructor super() calls.
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
Specifications
Browser compatibility
BCD tables only load in the browser
See also
Конструктор объектов в JS
Конструкторы в JavaScript — один из этапов создания объектов. Это специальные функции, которые позволяют инициализировать свойства объекта до создания. Например:
// конструктор объекта Person function Person () < this.name = 'Андрей', this.age = 23 >// создание объекта const person = new Person();
В этом примере function Person() — конструктор. Объект person создается с помощью ключевого слова new .
Совет. Правило хорошего тона — записывать имя функции-конструктора с большой буквы.
Создание нескольких объектов с помощью одного конструктора
В JavaScript с помощью одного конструктора можно создать несколько объектов. Например, вот так:
// функция-конструктор function Person () < this.name = 'Андрей', this.age = 23, >// создание объектов const person1 = new Person(); const person2 = new Person(); // доступ к свойствам console.log(person1.name); // Вывод: Андрей console.log(person2.name); // Вывод: Андрей
Ключевое слово this в конструкторе
Когда ключевое слово this используется в функции-конструкторе, оно относится к будущему объекту, который будет создан с помощью этого конструктора.
// функция-конструктор function Person () < this.name = 'Андрей', >// создание объекта const person1 = new Person(); // доступ к свойству name console.log(person1.name); // Вывод: Андрей
Когда мы создаем объект person1 с помощью конструктора Person() , this ссылается на person1 . Свойство name = ‘Андрей’ присваивается person1 .
Конструктор с параметрами
В JavaScript можно указать параметры для функции-конструктора. При создании объекта нужно будет передать соответсвующие аргументы.
// функция-конструктор с параметрами function Person (person_name, person_age, person_gender) < // инициализируем свойства соответствующими параметрами this.name = person_name, this.age = person_age, this.gender = person_gender, >// создание объекта — передаем аргументы const person1 = new Person('Андрей', 23, 'М'); const person2 = new Person('Маша', 25, 'Ж'); // доступ к свойствам объектов console.log(person1.age); // Вывод: 23 console.log(person2.name); // Вывод: Маша
Отличие простого объявления от конструктора
Количество объектов
→ Без конструктора можно обойтись, если создается один объект.
Например, если нам нужен объект одного человека — можно просто объявить его.
→ Конструктор полезен, если нужно создавать несколько объектов.
Если предполагается несколько объектов человек — лучше использовать конструктор.
function Person () < this.name = 'Андрей' >let person1 = new Person(); let person2 = new Person();
Уникальность объектов
→ Объекты, созданные без конструктора, не уникальны. Это значит, что если изменить какое-то свойство у переменной такого объекта, изменения отразяться и на оригинальном объекте. Например:
let person = < name: 'Андрей' >console.log(person.name); // Вывод: Андрей // создаем переменную student, которая является объектом person let student = person; // изменяем свойство name student.name = 'Дима'; // изменения затронули не только переменную student, // но и объект person console.log(person.name); // Вывод: Дима
→ Объекты, созданные с помощью конструктора, уникальны. Поэтому каждому объекту после создания можно отдельно добавлять свойства, которых не было в конструторе.
function Person () < this.name = 'Андрей' >let person1 = new Person(); let person2 = new Person(); // добавляем новое свойство age объекту person1 person1.age = 20;
Теперь свойство age есть только у объекта person1 . А у объекта person2 его нет.
Добавление свойств и методов в объект
В объект можно добавить свойства и методы следующим образом:
function Person () < this.name = 'Андрей', this.age = 23 >// создание объектов let person1 = new Person(); let person2 = new Person(); // добавление нового свойства gender объекту person1 person1.gender = 'М'; // добавление нового свойства greet объекту person person1.greet = function () < console.log('Привет'); >person1.greet(); // Вывод: Привет // Следующий код вызовет ошибку, // поскольку у объекта person2 нет метода greet() person2.greet();
Привет Uncaught TypeError: person2.greet is not a function
В этом выше примере к объекту person1 добавляется новое свойство gender и новый метод greet() .
Однако эти свойства и метод не добавляются к объекту person2 . Получить доступ к gender или greet() из person2 не получится — это вызовет ошибку.
Встроенные конструкторы
В JavaScript уже встроено большое количество конструкторов. Вот некоторые из них для примера:
let a = new Object(); // новый объект типо Object let b = new String(); // новый объект типо String let c = new Number(); // новый объект типо Number let d = new Boolean(); // новый объект типо Boolean
Как использовать
Вот несколько примеров того, как можно создавать объекты некоторых типов:
Строки
let name = new String ('Андрей'); console.log(name); // Вывод: Андрей
Числа
let number = new Number (57); console.log(number); // Вывод: 57
Логические значения
let count = new Boolean(true); console.log(count); // Вывод: true
Совет. Лучше все же использовать примитивные типы данных и создавать соответствующие переменные как обычно let name = ‘Андрей’ , let number = 57 и let count = true . Создание через объекты будет сильно нагружать программу.
СodeСhick.io — простой и эффективный способ изучения программирования.
2023 © ООО «Алгоритмы и практика»