Function: prototype
prototype
は Function
インスタンスのデータプロパティで、関数が new
演算子でコンストラクターとして使用されたときに使用されます。これは新しいオブジェクトのプロトタイプになります。
値
オブジェクトです。
Function: prototype のプロパティ属性 | |
---|---|
書込可能 | 可 |
列挙可能 | 不可 |
設定可能 | 不可 |
メモ: クラスは関数の一種なので、ここで説明するほとんどの内容はクラスの prototype
プロパティにも当てはまります。唯一の顕著な違いは、クラスの prototype
プロパティは書き込み不可であるということです。
解説
関数が new
で呼び出されると、そのコンストラクターの prototype
プロパティが、結果オブジェクトのプロトタイプになります。
function Ctor() {}
const inst = new Ctor();
console.log(Object.getPrototypeOf(inst) === Ctor.prototype); // true
「継承とプロトタイプチェーン」に、コンストラクター関数の prototype
プロパティと、結果オブジェクトのプロトタイプ間の操作に関する詳しい情報があります。
ある関数に prototype
プロパティがあるというだけでは、コンストラクターとして認められるには不十分です。ジェネレーター関数は prototype
プロパティを持っていますがが、 new
で呼び出すことはできません。
async function* asyncGeneratorFunction() {}
function* generatorFunction() {}
代わりに、ジェネレーター関数の prototype
プロパティは、 new
なしで呼び出されたときに使われます。prototype
プロパティは、返される Generator
オブジェクトのプロトタイプとなります。
さらに、一部の関数は prototype
を持っていても、 new
で呼び出された場合は無条件に例外を送出します。例えば、 Symbol()
関数や BigInt()
関数は、 new
で呼び出された場合には例外を発生させます。 Symbol.prototype
と BigInt.prototype
は、プリミティブ値のメソッドを提供するだけのためにあるので、ラッパーオブジェクトが直接構築されるべきではないからです。
次の関数には prototype
がなく、たとえ後で prototype
プロパティを手動で割り当てたとしても、コンストラクターとしては不適格です。
const method = { foo() {} }.foo;
const arrowFunction = () => {};
async function asyncFunction() {}
以下のものは有効なコンストラクターであり、 prototype
があります。
class Class {}
function fn() {}
バインドされた関数は prototype
プロパティを持っていませんが、構築することができる場合があります。 構築された場合、代わりにターゲット関数が構築され、ターゲット関数が構築可能であれば、通常のインスタンスを返します。
const boundFunction = function () {}.bind(null);
関数の prototype
プロパティは、既定では、1つのプロパティ constructor
を持つプレーンオブジェクトです。 constructor
プロパティは書き込み可能で、列挙不可、構成可能なプロパティです。
関数の prototype
が Object
以外の何かに再代入されている場合、関数が new
で呼び出されると、返されるオブジェクトのプロトタイプは Object.prototype
になります。(言い換えれば、new
は prototype
プロパティを無視し、プレーンなオブジェクトを構築します。)
function Ctor() {}
Ctor.prototype = 3;
console.log(Object.getPrototypeOf(new Ctor()) === Object.prototype); // true
例
prototype プロパティを変更することで、すべてのインスタンスのプロトタイプを変更
function Ctor() {}
const p1 = new Ctor();
const p2 = new Ctor();
Ctor.prototype.prop = 1;
console.log(p1.prop); // 1
console.log(p2.prop); // 1
クラスの prototype プロパティに、メソッド以外のプロパティを追加
クラスフィールドは、各インスタンスにプロパティを追加します。クラスメソッドは、プロトタイプに「関数」プロパティを宣言します。しかし、プロトタイプに「関数」以外のプロパティを追加する方法はありません。すべてのインスタンス間で静的データを共有したい場合(例えば、 Error.prototype.name
はすべてのエラーインスタンスで同じです)、クラスの prototype
に手動で割り当てることができます。
class Dog {
constructor(name) {
this.name = name;
}
}
Dog.prototype.species = "dog";
console.log(new Dog("Jack").species); // "dog"
これは、クラスが初期化される際に呼び出される静的初期化ブロックを使用することで、より人間に分かりやすくにすることができます。
class Dog {
static {
Dog.prototype.species = "dog";
}
constructor(name) {
this.name = name;
}
}
console.log(new Dog("Jack").species); // "dog"
仕様書
Specification |
---|
ECMAScript® 2025 Language Specification # sec-function-instances-prototype |