# 01. Constructor Function

Функции, вызываемые с оператором `new`, называются **конструкторами**. Конструкторы работают как фабрика для создания "похожих" объектов. Каждый конструктор определяет *класс объектов* --- это множество объектов, создаваемых при помощи этого конструктора.

> Технически, конструктором становится любая функция, вызванная через new. Любая функция может быть использована как конструктор. То есть, любую функцию можно вызвать при помощи `new`. Как-то особым образом указывать, что она — конструктор — не надо.

Функции-конструкторы имеют специальное свойство `prototype`, которое автоматически становится прототипом для создаваемых объектов. В `prototype` можно описать атрибуты и методы, которые будут у всех объектов, создаваемых при помощи этой функции-конструктора.

Основные особенности:

* Функции-конструкторы по соглашению обязаны именоваться с заглавной буквы `CamelCase`.
* Должны вызываться вместе с `new`.
* Должны возвращать новый экземпляр объекта с определенными свойствами, отражающего его принадлежность к классу конструктора.

## Usage

Процесс определения класса в языке JavaScript можно свести к трем этапам.

1. Написать функцию-конструктор, которая будет определять свойства экземпляра в новом объекте.
2. Определить методы экземпляров в объекте-прототипе конструктора.
3. Определить поля класса и свойства класса в самом конструкторе.

Алгоритм работы функции-конструктора `Constructor`, запущенной через `new Constructor()`:

* Автоматически создается новый пустой объект, с прототипом установленным в `Constructor.prototype`.
* Ключевое слово `this` внутри функции-конструктора получает ссылку на этот объект.
* Функция выполняется. Как правило, она модифицирует `this`, добавляет методы, свойства.
* Возвращается `this` (явный `return` указывать не нужно). Как правило, конструкторы ничего не возвращают. Их задача — записать всё, что нужно, в `this`, который автоматически станет результатом.
* Если явный вызов `return` всё же есть, то будет возвращён явный объект, а не `this`, который будет отброшен.

```javascript
// функция-конструктор
function Foo(y) {
  // которая умеет создавать объекты
  // по заданному шаблону: все эти объекты
  // будут иметь родное свойство "y"
  this.y = y;
}

// также "Foo.prototype" хранит ссылку
// на прототип вновь создаваемых объектов,
// поэтому мы можем использовать эту ссылку
// для созданиях наследуемых или разделяемых
// свойств; так же как и в предыдущем случае мы имеем:

// унаследованное свойство "x"
Foo.prototype.x = 10;

// и унаследованный метод"calculate"
Foo.prototype.calculate = function(z) {
  return this.x + this.y + z;
};

// создаём наши объекты "b" и "c"
// используя "шаблон" Foo
var b = new Foo(20);
var c = new Foo(30);

// вызываем унаследованный метод
b.calculate(30); // 60
c.calculate(40); // 80

// покажем, что мы работаем именно
// с теми свойствами, которые ожидаем

b.__proto__ === Foo.prototype, // true
  c.__proto__ === Foo.prototype, // true
  // также "Foo.prototype" автоматически создает
  // специальное свойство "constructor", являющееся
  // ссылкой на саму функцию-конструктор, т.е. на "Foo";
  // объекты "b" и "c" могут найти это свойство посредством
  // делегации и использовать его для проверки своего конструктора

  b.constructor === Foo, // true
  c.constructor === Foo, // true
  Foo.prototype.constructor === Foo, // true
  b.calculate === b.__proto__.calculate, // true
  b.__proto__.calculate === Foo.prototype.calculate; // true
```

Объект считается корректно созданным функцией-конструктором, если он обладает следующими особенностями:

* В поле `obj.constructor === Constructor` будет находится ссылка на его функцию-конструктор.
* В прототип объекта записывается значение `Constructor.prototype`, а именно `Object.setPrototypeOf(this, Constructor.prototype)`.
* Оператор `obj instanceof Constructor` будет возвращать `true`.
* Для системных объектов справедливо, что `Object.prototype.toString(obj)` вернет специальную строку с классом объекта.

## Return

Функция-конструктор может не иметь явного `return` в конце, хотя иметь один или несколько `return` конструктору не запрещено. Если в функции нет `return`, то в этом случае неявно возвращается создаваемый объект (`this`). Если же функция имеет `return`, то создаваемый объект отбрасывается и возвращается результат оператора `return`.

```javascript
function Article(content) {
  if (content.isEmpty()) {
    return Article.EMPTY_CONTENT;
  }
  this.count = Article.count;
  this.format = Article.DEFAULT_FORMAT;
  this.content = content;
}
```

## Static fields and instance fields

Избегайте хранить данные в прототипе конструктора. Не разделяйте между создаваемыми объектами в конструкторе начальные данные. Каждый создаваемый объект должен иметь свою копию начальных данных.

* *Поле класса* - свойство `this`-объекта конструктора, или свойство прототипа.
* *Метод класса* - метод `this`-объекта конструктора, или метод прототипа.

Методы и свойства, которые не привязаны к конкретному экземпляру объекта, называют «статическими». Если нужны глобальные данные, разделяемые между всеми экземплярами класса, то их записывают прямо в саму функцию-конструктор.

* *Статический метод* - метод функции-конструктора.
* *Статическое поле* - атрибут функции конструктора.

```javascript
function Article(content) {
  this.count = Article.count;
  this.format = Article.DEFAULT_FORMAT;
  this.content = content;
}

Article.count = 0; // статическое свойство-переменная
Article.DEFAULT_FORMAT = "html"; // статическое свойство-константа
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://strctr.gitbook.io/programming/01-languages/javascript/01-language/c-functions/c2-constructors/01-constructor-function.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
