constructor
===========

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

* Learn more
* See full compatibility
* Report feedback
**`constructor`** メソッドは、クラスで作成されたオブジェクトインスタンスの生成と初期化を行うための特殊なメソッドです。

**メモ:** このページでは `constructor` の構文を紹介します。すべてのオブジェクトに存在する `constructor` プロパティについては、 `Object.prototype.constructor` を参照してください。

試してみましょう
--------

構文
--


```js
constructor() { /\* … \*/ }
constructor(argument0) { /\* … \*/ }
constructor(argument0, argument1) { /\* … \*/ }
constructor(argument0, argument1, /\* …, \*/ argumentN) { /\* … \*/ }
```


追加の構文上の制約があります。

* `constructor` という名前のクラスメソッドは、ゲッター、セッター、非同期、ジェネレーターメソッドになることはできません。
* 1 つのクラスが複数の `constructor` メソッドを持つことはできません。
解説
--

コンストラクターを使用すると、インスタンス化されたオブジェクトに対して、他のメソッドを呼び出す前に行う必要のある独自の初期化を行うことができます。


```js
class Person {
  constructor(name) {
    this.name = name;
  }

  introduce() {
    console.log(`こんにちは、私は${this.name}です。`);
  }
}

const otto = new Person("オットー");

otto.introduce(); // こんにちは、私はオットーです。
```


独自のコンストラクターを提供しなかった場合は、既定のコンストラクターが提供されます。クラスが基底クラスである場合、既定のコンストラクターは空です。


```js
constructor() {}
```


クラスが派生クラスの場合、既定のコンストラクターが親コンストラクターを呼び出し、与えられた引数を渡します。


```js
constructor(...args) {
  super(...args);
}
```


**メモ:** 上記のような明示的なコンストラクターと既定のコンストラクターの異なる点は、後者が実際には配列イテレーターを呼び出して引数のスプレッドを行わないことです。

それがこのようなコードを動作させることができます。


```js
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); // これは ValidationError の代わりのエラー
    console.log(error.printCustomerMessage());
  } else {
    console.log("Unknown error", error);
    throw error;
  }
}
```


`ValidationError` クラスは、独自の初期化を行う必要がないため、明示的なコンストラクターは必要ありません。
 既定のコンストラクターは、与えられた引数から親の `Error` の初期化を行います。

 ただし、独自のコンストラクターを提供し、クラスが親クラスから派生している場合は、 `super()` を使用して親クラスのコンストラクターを明示的に呼び出す必要があります。
 例えば、以下のようになります。


```js
class ValidationError extends Error {
  constructor(message) {
    super(message); // 親クラスのコンストラクターの呼び出し
    this.name = "ValidationError";
    this.code = "42";
  }

  printCustomerMessage() {
    return `検証に失敗しました :-( (details: ${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;
  }
}
```


クラスで `new` を使用すると、以下の段階を踏みます。

1. （派生クラスの場合） `super()` 呼び出しが評価される前の `constructor` 本体。この部分はまだ初期化されていないので、 `this` にアクセスしてはいけません。
2. （派生クラスの場合） `super()` 呼び出しが評価され、同じ処理で親クラスが初期化されます。
3. 現在のクラスのフィールドが初期化されます。
4. `super()` 呼び出し後の `constructor` 本体（基底クラスの場合は本体全体）が評価されます。

`constructor` 本体の中では、 `this` で作成されるオブジェクトにアクセスしたり `new` で呼び出されるクラスに `new.target` でアクセスしたりすることができます。メソッド（ゲッター、セッターを含む）とプロトタイプチェーン は `constructor` が実行される前に `this` で初期化されているので、スーパークラスのコンストラクターからサブクラスのメソッドにアクセスすることもできることに注意してください。しかし、これらのメソッドが `this` を使用している場合、 `this` はまだ完全に初期化されていません。これは、派生クラスのパブリックフィールドを読むと `undefined` になり、プライベートフィールドを読むと `TypeError` になるということです。


```js
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
    // これは、クラスが宣言していないのではなく、スーパークラスの
    // コンストラクターが実行されている時点で、プライベートフィールドが
    // まだ初期化されていないため。
  }
})();
```


`constructor` メソッドは返値を持つことができます。基底クラスはコンストラクターから何らかの値を返すことができますが、派生クラスはオブジェクトまたは `undefined` を返すか、 `TypeError` を発生させなければなりません。


```js
class ParentClass {
  constructor() {
    return 1;
  }
}

console.log(new ParentClass()); // ParentClass {}
// 返値はオブジェクトではないので無視される。 これはコンストラクター関数と同じ。

class ChildClass extends ParentClass {
  constructor() {
    return 1;
  }
}

console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined
```


親クラスのコンストラクターがオブジェクトを返した場合、そのオブジェクトは派生クラスのクラスフィールドを定義する際の値として使用します。このトリックは「返値の上書き」と呼ばれ、派生クラスのフィールド（プライベートなものも含む）を無関係なオブジェクトに定義することができます。

`constructor` は通常のメソッド構文に従うので、デフォルト引数や残余引数などをすべて使用することができます。


```js
class Person {
  constructor(name = "名無し") {
    this.name = name;
  }
  introduce() {
    console.log(`こんにちは、私は${this.name}`);
  }
}

const person = new Person();
person.introduce(); // こんにちは、私は名無し
```


コンストラクターはリテラル名でなければなりません。計算されたプロパティ名はコンストラクターにはなれません。


```js
class Foo {
  // これは計算プロパティ名です。コンストラクターとしてピックアップされることはありません。
  ["constructor"]() {
    console.log("called");
    this.a = 1;
  }
}

const foo = new Foo(); // ログ出力なし
console.log(foo); // Foo {}
foo.constructor(); // "called" と出力
console.log(foo); // Foo { a: 1 }
```


非同期メソッド、ジェネレータメソッド、アクセサ、クラスフィールドは `constructor` と名付けることは禁止されています。プライベートな名前を `#constructor` と呼び出すことはできません。 `constructor` という名前のメンバーはプレーンなメソッドでなければなりません。

例
-

### constructor メソッドの使用

このコードスニペットは、classes sample (ライブデモ) から転載しています。


```js
class Square extends Polygon {
  constructor(length) {
    // ここでは、ポリゴンの幅と高さを指定された長さにして、親クラスの
    // コンストラクターを呼び出しています。
    super(length, length);
    // メモ: 派生クラスでは、`this` を使用する前に `super()` を呼び出す
    // 必要があります。これを省略すると 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()` が呼び出すコンストラクターには影響しません。


```js
class Polygon {
  constructor() {
    this.name = "Polygon";
  }
}

class Rectangle {
  constructor() {
    this.name = "Rectangle";
  }
}

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

// Polygon の代わりに（基本クラスである） Rectangle を継承するようにする
Object.setPrototypeOf(Square, Rectangle);

const newInstance = new Square();

// newInstance はまだ Polygon のインスタンスです。
// Square.prototype のプロトタイプを変更していないので、
// newInstance のプロトタイプチェーンは以下のままです。
// newInstance --> Square.prototype --> Polygon.prototype
console.log(newInstance instanceof Polygon); // true
console.log(newInstance instanceof Rectangle); // false

// ただし、 super() はコンストラクターとして Rectangle を呼び出すため、
// newInstance の name プロパティは Rectangle のロジックで初期化されます。
console.log(newInstance.name); // Rectangle
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-static-semantics-constructormethod |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* クラスの使用ガイド
* クラス
* 静的初期化ブロック
* `class`
* `super()`
* `Object.prototype.constructor`