JavaScript の継承およびコンストラクタのプロトタイプの説明については、継承とコンストラクタのプロトタイプをご覧ください。
JavaScript では継承が常に使用可能ですが、このページの例では ECMAScript 5 で導入されたメソッドをいくつか使用します。それらがエミュレート可能であるかについては、各メソッド個別のページをご覧ください。
例
B は A から継承するでしょう:
function A(a){
this.varA = a;
}
A.prototype = {
varA : null,
doSomething : function(){
// ...
}
}
function B(a, b){
A.call(this, a);
this.varB = b;
}
B.prototype = Object.create(new A(), {
varB : { value: null, enumerable: true, configurable: true, writable: true },
doSomething : { value: function(){ // オーバーライド
A.prototype.doSomething.apply(this, arguments); // 上位の呼び出し
// ...
}, enumerable: true, configurable: true, writable: true }
})
var b = new B();
b.doSomething();
ここでは以下の点が重要です:
- 型は
.prototypeで定義されます。 - 継承するために
Object.create()を使用します。
prototype と Object.getPrototypeOf
Java や C++ を経験してきた開発者にとって JavaScript は、すべてが動的であり、すべてが実行時に決まり、そしてクラスがまったく存在しないことから、ややわかりにくい言語です。JavaScript では単純に、すべてがインスタンス (オブジェクト) です。"クラス" をシミュレートしているものでさえ、単なる関数オブジェクトです。
すでに気づいているかもしれませんが、function A は prototype と呼ばれる特別なプロパティを持っています。この特別なプロパティは、JavaScript の new とともに働きます。プロトタイプオブジェクトへの参照は、新たなインスタンスの内部にある [[Prototype]] プロパティにコピーされます。例えば var a1 = new A() という処理を行うとき、JavaScript は (オブジェクトをメモリ内に作成した後、かつそのオブジェクトを this に定義して A() を実行する前) に a1.[[Prototype]] = A.prototype をセットします。そしてインスタンスのプロパティにアクセスするとき、JavaScript はまず、オブジェクト上にそれらが直接存在しているかを確認します。存在しない場合は、[[Prototype]] を参照します。これは prototype で定義したすべての内容が、すべてのインスタンスで効率的に共有されることを意味します。また、必要に応じて prototype の一部を後から変更したり、その変更を存在する全インスタンスに反映させることもできます。
前出の例で var a1 = new A(); var a2 = new A(); を実行したとき、a1.doSomething は実際は Object.getPrototypeOf(a1).doSomething を参照しており、これは A.prototype.doSomething と同じです。すなわち、Object.getPrototypeOf(a1).doSomething == Object.getPrototypeOf(a2).doSomething == A.prototype.doSomething です。
簡潔に言うと、prototype は型のためのものであり、一方 Object.getPrototypeOf() はインスタンスと同じです。
[[Prototype]] は再帰的に参照されます。すなわち a1.doSomething、Object.getPrototypeOf(a1).doSomething、Object.getPrototypeOf(Object.getPrototypeOf(a1)).doSomething というように、doSomething が見つかるか Object.getPrototypeOf が null を返すまで続けます。
よって、次のように呼び出したとき:
var o = new Foo();
JavaScript は、実際には以下のように実行します:
var o = new Object(); o.[[Prototype]] = Foo.prototype; o.Foo();
(あるいは類似の何らかの処理を行います) また、その後以下の処理を行うとき:
o.someProp;
JavaScript は o が someProp を持っているかを確認します。持っていない場合は Object.getPrototypeOf(o).someProp を確認し、ここにも存在しない場合は Object.getPrototypeOf(Object.getPrototypeOf(o)).someProp を確認、などというように動作します。