aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/javascript/reference/classes/constructor/index.html
blob: 81546fdb275bbdfb0023ec6d66c566777e68ab43 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
---
title: constructor
slug: Web/JavaScript/Reference/Classes/constructor
tags:
  - ECMAScript 2015
  - ES6
  - JavaScript
  - Классы
translation_of: Web/JavaScript/Reference/Classes/constructor
---
<div>{{jsSidebar("Classes")}}</div>

<div><code>constructor</code> - это специальный метод, служащий для создания и инициализации объектов, созданных с использованием <code>class</code>.</div>

<h2 id="Синтаксис">Синтаксис</h2>

<pre class="syntaxbox">constructor([arguments]) { ... }</pre>

<h2 id="Описание">Описание</h2>

<p>Конструктор позволяет произвести начальную инициализацию, которая должна быть выполнена до того, как остальные методы будут вызваны.</p>

<pre>class Person {

  constructor(name) {
    this.name = name;
  }

  introduce() {
    console.log(`Hello, my name is ${this.name}`);
  }

}

const otto = new Person('Отто');

otto.introduce();</pre>

<p>Если вы не определили метод constructor, то будет использован конструктор по умолчанию. Если ваш класс базовый, то конструктор по умолчанию пустой:</p>

<pre>constructor() {}</pre>

<p>Если ваш класс является производным классом, конструктор по умолчанию вызывает родительский конструктор, передавая любые аргументы, которые были предоставлены:</p>

<pre>constructor(...args) {
  super(...args);
}</pre>

<p>Это позволяет работать следующему коду:</p>

<pre>class ValidationError extends Error {

  printCustomerMessage() {
    return `Проверка не удалась :-( (подробности: ${this.message})`;
  }

}

try {
  throw new ValidationError("Неправильный номер телефона");
} catch (error) {
   if (error instanceof ValidationError) {
    console.log(error.name); // Это Error вместо ValidationError!
    console.log(error.printCustomerMessage());
  } else {
    console.log('Неизвестная ошибка', error);
    throw error;
  }
}</pre>

<p><code>ValidationError</code> классу не нужен явный (explicit) конструктор, потому что не требуется инициализация. Затем, конструктор по умолчанию позаботится об инициализации родительского класса <code>Error</code>, переданным ему аргументом.</p>

<p>Однако, если определён ваш собственный конструктор и класс является производным от какого-либо родительского класса, то вы должны явно объявить конструктор родительского класса, используя <code>super</code>. К примеру:</p>

<pre>class ValidationError extends Error {

  constructor(message) {
    super(message);  // вызов конструктора родительского класса
    this.name = 'ValidationError';
    this.code = '42';
  }

  printCustomerMessage() {
     return `Проверка не удалась :-( (подробности: ${this.message}, code: ${this.code})`;
  }

}

try {
  throw new ValidationError("Неправильный номер телефона");
} catch (error) {
   if (error instanceof ValidationError) {
    console.log(error.name); // Теперь это ValidationError!
    console.log(error.printCustomerMessage());
  } else {
    console.log('Неизвестная ошибка', error);
    throw error;
  }
}</pre>

<p>В классе может быть только один метод с именем "<code>constructor</code>". Если класс содержит более одного <code>constructor</code>, будет сгенерировано исключение {{jsxref("SyntaxError")}}.</p>

<h2 id="Примеры">Примеры</h2>

<h3 id="Использование_метода_constructor">Использование метода <code>constructor</code></h3>

<p>Данный фрагмент кода взят из <a href="https://github.com/GoogleChrome/samples/blob/gh-pages/classes-es6/index.html">classes sample</a> (<a href="https://googlechrome.github.io/samples/classes-es6/index.html">live demo</a>).</p>

<pre class="brush: js">class Square extends Polygon {
  constructor(length) {
    // Здесь вызывается конструктор родительского класса,
    // в который передаётся length в качестве аргументов,
    // соответствующим полям width и height класса Polygon
    super(length, length);
    // Примечание: В производном классе, super() должен вызываться перед тем, как
    // вы сможете использовать 'this'. Иначе будет сгенерировано исключение reference error.
    this.name = 'Square';
  }

  get area() {
    return this.height * this.width;
  }

  set area(value) {
    this.area = value;
  }
}</pre>

<h3 id="Другой_пример">Другой пример</h3>

<p>Посмотрите на этот отрывок кода.</p>

<pre class="brush: js">class Polygon {
  constructor() {
    this.name = "Polygon";
  }
}

class Square extends Polygon {
  constructor() {
    super();
  }
}

class Rectangle {}

Object.setPrototypeOf(Square.prototype, Rectangle.prototype);

console.log(Object.getPrototypeOf(Square.prototype) === Polygon.prototype); //false
console.log(Object.getPrototypeOf(Square.prototype) === Rectangle.prototype); //true

let newInstance = new Square();
console.log(newInstance.name); //Polygon</pre>

<p>Здесь прототип <strong>Square</strong> класса изменён, но в то же время constructor предыдущего базового класса <strong>Polygon</strong> вызывается при создании нового экземпляра <strong>Square</strong>.</p>

<h3 id="Constructors_по_умолчанию.">Constructors по умолчанию.</h3>

<p>Если вы не определите метод constructor, будет использован constructor по умолчанию. Для базовых классов, constructor по умолчанию:</p>

<pre class="brush: js">constructor() {}</pre>

<p>Для производных классов, constructor по умолчанию:</p>

<pre class="brush: js">constructor(...args) {
  super(...args);
}</pre>

<h2 id="Спецификация">Спецификация</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('ES2015', '#sec-static-semantics-constructormethod', 'Constructor Method')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td>Изначальное определение.</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-static-semantics-constructormethod', 'Constructor Method')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2>
<p>{{Compat("javascript.classes.constructor")}}</p>

<h2 id="Смотрите_также">Смотрите также</h2>

<ul>
 <li><a href="/ru/docs/Web/JavaScript/Reference/Operators/super">super()</a></li>
 <li><a href="/ru/docs/Web/JavaScript/Reference/Operators/class"><code>class</code> expression</a></li>
 <li><a href="/ru/docs/Web/JavaScript/Reference/Statements/class"><code>class</code> declaration</a></li>
 <li><a href="/ru/docs/Web/JavaScript/Reference/Classes">Classes</a></li>
 <li><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">Object.prototype.constructor</a></li>
</ul>