詳しくは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.prototypeFoo.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に到達しても、検索する必要がある属性が見つからない場合、Javascriptundefinedの値を返します.
プロトタイプオブジェクトのプロパティ
プロトタイプオブジェクトのプロパティは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