詳しくはJavascriptオブジェクト編(二):プロトタイプオブジェクト
3238 ワード
Javascript
はクラス継承モデルではなく、プロトタイプオブジェクトprototype
を使用してプロトタイプ継承を行う.これをJavascript
の欠点と見なすことが多いが、実際には、プロトタイプ継承は従来のクラス継承モデルよりも強力である.例を挙げると,プロトタイプ継承の先端にクラスモデルを構築するのは簡単であるが,逆に困難なタスクである.Javascript
は、広く用いられている唯一のプロトタイプ継承言語であるため、2つの継承方式の違いを理解するには時間がかかる.最初の主な違いは、
Javascript
がプロトタイプチェーンを使用して継承することです.function Foo() {
this.value = 42;
}
Foo.prototype = {
method: function() {}
};
function Bar() {}
Bar
に設定されたprototype
は、Foo
のオブジェクトインスタンスです.Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';
Bar
のコンストラクション関数がそれ自体であることを確認し、Bar
オブジェクトインスタンスを新規作成します.Bar.prototype.constructor = Bar;
var test = new Bar();
プロトタイプチェーン全体の構成を見てみましょう.
test [instance of Bar]
Bar.prototype [instance of Foo]
{ foo: 'Hello World' }
Foo.prototype
{ method: ... }
Object.prototype
{ toString: ... /* etc. */ }
上記の例では、オブジェクト
test
は、Bar.prototype
とFoo.prototype
とを同時に継承する.したがって、Foo
に定義された関数method
にアクセスすることができる.もちろん、プロパティvalue
にもアクセスできます.なお、new Bar()
の場合、新しいFoo
インスタンスは作成されず、そのプロトタイプオブジェクトに付属するFoo
インスタンスが再利用される.同様に、すべてのBar
インスタンスは、同じvalue
属性を共有する.例を挙げて説明します. test1 = new Bar();
test2 = new Bar();
Bar.prototype.value = 41;
test1.value //41
test2.value//41
プロトタイプチェーン検索メカニズム
オブジェクトのプロパティにアクセスすると、
Javascript
は、対応するプロパティが見つかるまで、オブジェクト自体からプロトタイプチェーン全体を巡ります.このとき、プロトタイプチェーンの上部、すなわち前例のObject.prototype
に到達しても、検索する必要がある属性が見つからない場合、Javascript
はundefined
の値を返します.プロトタイプオブジェクトのプロパティ
プロトタイプオブジェクトのプロパティは
Javascript
によってプロトタイプチェーンを構築するために使用されますが、値を割り当てることができます.ただし、元の値をprototype
にコピーするのは無効です.function Foo() {}
Foo.prototype = 1; // no effect
ここで、本編の余談ですが、元の値とは何かを紹介します.
Javascript
では、変数は元の値と参照値の2種類の値を格納できます.1.元の値
(primitive value)
:元の値は固定された単純な値であり、スタックstack
に格納された単純なデータセグメントであり、すなわち、それらの値は変数アクセスの位置に直接格納される.元のタイプには、Undefined, Null, Boolean, Number, String
の5つのタイプがあります.2.参照値
(reference value)
:参照値は比較的大きなオブジェクトであり、スタックheap
に格納されたオブジェクト、すなわち、変数に格納された値は、格納されたオブジェクトのメモリを指すポインタpointer
である.すべての参照タイプはObject
から統合されています.プロトタイプチェーンのパフォーマンスの問題
検索するプロパティがプロトタイプチェーンの上端にある場合、検索プロセスはパフォーマンスに悪影響を及ぼすに違いありません.パフォーマンスが必要とされるシーンでは、考慮すべき要素になります.また、アトリビュートが存在しない場合は、プロトタイプチェーン全体を巡回します.同様に、オブジェクトのプロパティを巡回すると、プロトタイプチェーン上のすべてのプロパティがアクセスされます.
まとめ
プロトタイプ継承を理解することは、複雑な
Javascript
コードを書く前提であり、コード内のプロトタイプチェーンの高さに注意しなければならない.パフォーマンスのボトルネックに直面している場合は、プロトタイプチェーンを分割することを学ばなければなりません.また、プロトタイプオブジェクトprototype
とプロトタイプ__proto__
を区別するには、ここで主にプロトタイプオブジェクトprototype
についてはプロトタイプ__proto__
については述べないが、疑問があれば@nightireヴァンゴーのブログ「JavaScriptを理解する(四)」を読むことができる.リファレンス
http://bonsaiden.github.io/JavaScript-Garden/#object.prototype