Movatterモバイル変換


[0]ホーム

URL:


  1. 開発者向けのウェブ技術
  2. JavaScript
  3. JavaScript リファレンス
  4. 標準組み込みオブジェクト
  5. Object
  6. constructor

このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docsコミュニティーについてもっと知り、仲間になるにはこちらから。

View in EnglishAlways switch to English

Object.prototype.constructor

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since ⁨2015年7月⁩.

constructorObject インスタンスのデータプロパティで、インスタンスオブジェクトを生成したコンストラクター関数への参照を返します。なお、このプロパティの値は関数そのものへの参照であり、関数名を含んだ文字列ではありません。

メモ:これは JavaScript オブジェクトのプロパティです。クラスのconstructor メソッドについては、リファレンスページを参照してください。

インスタンスオブジェクトを作成したコンストラクター関数への参照。

Object.prototype.constructor のプロパティ属性
書込可能
列挙可能不可
設定可能

メモ:このプロパティは、既定ではすべてのコンストラクター関数のprototype プロパティに作成され、そのコンストラクターで作成されたすべてのオブジェクトに継承されます。

解説

null プロトタイプオブジェクトを除く)どんなオブジェクトも、その[[Prototype]] にコンストラクターのプロパティを持っています。例えば、配列リテラルはArray オブジェクトを作成し、オブジェクトリテラル はプレーンオブジェクトを作成します。

js
const o1 = {};o1.constructor === Object; // trueconst o2 = new Object();o2.constructor === Object; // trueconst a1 = [];a1.constructor === Array; // trueconst a2 = new Array();a2.constructor === Array; // trueconst n = 3;n.constructor === Number; // true

通常constructor はコンストラクターのprototype プロパティに決まります。より長いプロトタイプチェーンがある場合、通常、チェーン内のすべてのオブジェクトがconstructor プロパティを持つことが期待できます。

js
const o = new TypeError(); // 継承: TypeError -> Error -> Objectconst proto = Object.getPrototypeOf;Object.hasOwn(o, "constructor"); // falseproto(o).constructor === TypeError; // trueproto(proto(o)).constructor === Error; // trueproto(proto(proto(o))).constructor === Object; // true

オブジェクトのコンストラクターの表示

以下の例では、コンストラクター (Tree) と、その型のオブジェクト (theTree) を生成します。そして、theTree オブジェクトのconstructor プロパティを表示します。

js
function Tree(name) {  this.name = name;}const theTree = new Tree("Redwood");console.log(`theTree.constructor is ${theTree.constructor}`);

この例の出力は次のとおりです。

theTree.constructor is function Tree(name) {  this.name = name;}

オブジェクトへの constructor プロパティの代入

constructor プロパティにプリミティブ以外を代入することができます。

js
const arr = [];arr.constructor = String;arr.constructor === String; // truearr instanceof String; // falsearr instanceof Array; // trueconst foo = new Foo();foo.constructor = "bar";foo.constructor === "bar"; // true// etc.

これは古いconstructor プロパティを上書きしません。これはもともとインスタンスの[[Prototype]] に存在するものであり、独自のプロパティではないからです。

js
const arr = [];Object.hasOwn(arr, "constructor"); // falseObject.hasOwn(Object.getPrototypeOf(arr), "constructor"); // truearr.constructor = String;Object.hasOwn(arr, "constructor"); // true — インスタンスプロパティがプロトタイプのプロパティを隠す

しかし、Object.getPrototypeOf(a).constructor が代入し直されても、オブジェクトの他の動作は変わりません。例えば、instanceof の動作はconstructor ではなく、Symbol.hasInstance によって制御されます。

js
const arr = [];arr.constructor = String;arr instanceof String; // falsearr instanceof Array; // true

constructor プロパティは、再代入されたりシャドウ化されたりしないように保護するものは何もありません。したがって、変数の型を検出するためにコンストラクターを使用することは通常避けるべきで、オブジェクトの場合はinstanceofSymbol.toStringTag、プリミティブの場合はtypeof のような壊れにくい方法を選ぶべきです。

コンストラクター関数のプロトタイプのコンストラクターを変更

すべてのコンストラクターはprototype プロパティを持っており、このプロパティはnew 演算子で呼び出されたときにインスタンスのプロトタイプ ([[Prototype]]) になります。従って、コンストラクター関数ConstructorFunction.prototype.constructor は前回示したように、インスタンスの[[Prototype]] のプロパティになります。

しかし、ConstructorFunction.prototype に再代入されると、constructor プロパティは失われます。例えば、次の例は継承パターンを作成する一般的な方法です。

js
function Parent() {  // …}Parent.prototype.parentMethod = function () {};function Child() {  Parent.call(this); // すべてが正しく初期化されていることを確認}// 子のプロトタイプを親のプロトタイプで再定義Child.prototype = Object.create(Parent.prototype);

Child のインスタンスのconstructorChild.prototype が再割り当てされるため、Parent になります。

言語がオブジェクトのconstructor プロパティを読み取ることはほとんどありません。唯一の例外は、クラスの新しいインスタンスを作成するために[Symbol.species] を使用する場合ですが、そのような用途はまれであり、いずれにせよ、組み込みクラスのサブクラスを作成するためにはextends 構文を使用する必要があります。

しかし、呼び出し側がインスタンスから元クラスにアクセスするためにconstructor を使用している場合、Child.prototype.constructor が常にChild 自体を指していることを保証することは非常に重要です。以下はオブジェクトを作成するためのcreate() メソッドを持っている場合です。

js
function Parent() {  // …}function CreatedConstructor() {  Parent.call(this);}CreatedConstructor.prototype = Object.create(Parent.prototype);CreatedConstructor.prototype.create = function () {  return new this.constructor();};new CreatedConstructor().create().create(); // TypeError: new CreatedConstructor().create().create は undefined、 constructor === Parent だから

上の例では、constructorParent にリンクしているため、例外が発生します。これを避けるには、使用するコンストラクターを割り当ててください。

js
function Parent() {  // …}function CreatedConstructor() {  // …}CreatedConstructor.prototype = Object.create(Parent.prototype, {  // Child の下のコンストラクターを返す  constructor: {    value: CreatedConstructor,    enumerable: false, // 列挙不可にすることで、 `for...in` ループで現れないようにする    writable: true,    configurable: true,  },});CreatedConstructor.prototype.create = function () {  return new this.constructor();};new CreatedConstructor().create().create(); // うまく動作する

constructor のプロパティを手動で追加する場合は、そのプロパティを列挙不可にすることが重要です。そうすれば、constructorfor...in ループで参照されることはなくなります。

上記のコードが定型文のように見える場合は、Object.setPrototypeOf() を使用してプロトタイプチェーンを操作することもできます。

js
function Parent() {  // …}function CreatedConstructor() {  // …}Object.setPrototypeOf(CreatedConstructor.prototype, Parent.prototype);CreatedConstructor.prototype.create = function () {  return new this.constructor();};new CreatedConstructor().create().create(); //コンストラクタープロパティを再作成することなく動作する

Object.setPrototypeOf() は、プロトタイプチェーンに関与する前回作成したすべてのオブジェクトを再コンパイルする必要があるため、潜在的なパフォーマンス上のデメリットを伴いますが、上記の初期化コードがParent またはCreatedConstructor が作成される前に発生する場合、効果は最小限になるはずです。

もう一つの例を考えてみましょう。

js
function ParentWithStatic() {}ParentWithStatic.startPosition = { x: 0, y: 0 }; // 静的メンバープロパティParentWithStatic.getStartPosition = function () {  return this.startPosition;};function Child(x, y) {  this.position = { x, y };}Child.prototype = Object.create(ParentWithStatic.prototype, {  // Return original constructor to Child  constructor: {    value: Child,    enumerable: false,    writable: true,    configurable: true,  },});Child.prototype.getOffsetByInitialPosition = function () {  const position = this.position;  // getStartPosition が静的メソッドとして存在することを期待して this.constructor を使用  const startPosition = this.constructor.getStartPosition();  return {    offsetX: startPosition.x - position.x,    offsetY: startPosition.y - position.y,  };};new Child(1, 1).getOffsetByInitialPosition();// Error: this.constructor.getStartPosition is undefined, since the// constructor is Child, which doesn't have the getStartPosition static method

この例が正しく動作するように、Parent の静的プロパティをChild に再割り当てします。

js
// …Object.assign(Child, ParentWithStatic); // Notice that we assign it before we create() a prototype belowChild.prototype = Object.create(ParentWithStatic.prototype, {  // Return original constructor to Child  constructor: {    value: Child,    enumerable: false,    writable: true,    configurable: true,  },});// …

しかし、さらに良いことに、クラスのextends のように、コンストラクター関数自体を互いに拡張させることができます。

js
function ParentWithStatic() {}ParentWithStatic.startPosition = { x: 0, y: 0 }; // 静的メンバープロパティParentWithStatic.getStartPosition = function () {  return this.startPosition;};function Child(x, y) {  this.position = { x, y };}// Properly create inheritance!Object.setPrototypeOf(Child.prototype, ParentWithStatic.prototype);Object.setPrototypeOf(Child, ParentWithStatic);Child.prototype.getOffsetByInitialPosition = function () {  const position = this.position;  const startPosition = this.constructor.getStartPosition();  return {    offsetX: startPosition.x - position.x,    offsetY: startPosition.y - position.y,  };};console.log(new Child(1, 1).getOffsetByInitialPosition()); // { offsetX: -1, offsetY: -1 }

繰り返しますが、Object.setPrototypeOf()を使用するとパフォーマンスに悪影響を持つことがあるので、コンストラクター宣言の直後でインスタンスが作成される前に使用するようにしてください。

メモ:コンストラクターを手動で更新したり設定したりすると、異なる結果や混乱する結果を導くことがあります。これを防ぐためには、それぞれの場合に応じてconstructor の役割を定義することが必要です。多くの場合、constructor 使用されず、再割り当ての必要はありません。

仕様書

Specification
ECMAScript® 2026 Language Specification
# sec-object.prototype.constructor

ブラウザーの互換性

関連情報

Help improve MDN

Learn how to contribute

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp