Function: prototype
値
オブジェクトです。
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); // 1console.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® 2026 Language Specification # sec-function-instances-prototype |