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
を確認、などというように動作します。