Javascriptのオブジェクト向けを整理する(一)——プロトタイプ継承


他のプログラミング言語とは異なり、javascriptのオブジェクト向けは抽象的なクラスに依存するのではなく、 を介して特定のオブジェクトインスタンスを接続し、プロトタイプチェーンの下流にあるオブジェクトインスタンスは上流にあるオブジェクトインスタンスの属性/方法を読み取り/使用することができる.以下では,javascriptのオブジェクト向けの本質を一歩一歩整理しようとする.

万物の源:javascriptの原生タイプ――Object


JAvascriptは、最も基礎的なオブジェクトタイプObjectを定義し、このオブジェクトタイプのために多くのメンバーメソッドを定義します.他の多くのオリジナルオブジェクトタイプは、実際にはObject、例えばFunctionDateなどから継承される.Objectオブジェクトタイプのオブジェクトインスタンスを生成するのも難しいことではありません.
var obj = {a: 2333};
//      Object()      
var obj = new Object();

実際には,オブジェクト指向性の方が構造関数を用いてオブジェクトインスタンスを生成するべきである.

オブジェクトインスタンスを生成する演算子newと構造関数constructor


newという演算子を使用してオブジェクトインスタンスを生成する方法


他のプログラミング言語では、newもオブジェクトインスタンスを生成するために使用されることが多い.一般的には、new ClassName[([arguments])]であり、生成されたオブジェクトインスタンスも「ClassNameオブジェクト」という呼称を冠している.Javascriptは大きく異なり、原生にはクラスという概念がないため、 new constructor[([arguments])]に代わり、呼称も「constructorオブジェクト」や「constructorタイプのオブジェクト」に変更され、構造関数名は直接データ型に等しい.
function A() {}    //    (        ,       ) A。
var obj = new A();    //      A       obj
console.dir(obj);    //      obj

上の図から分かるように、コンストラクション関数Aを用いて生成されるインスタンスオブジェクトobjのデータ型はAであり、また、objには__proto__の属性が1つしかないことに留意すると、これは何であるか.焦らないで、後で話します.

コンストラクション関数constructorの詳細


以上から分かるように、オブジェクトインスタンスを生成するには、constructorまたはvar arr = [];のような形式であってもjavascriptは、var obj = {}Function()のような予め設定された構造関数を内部的に呼び出す(予め設定された構造関数/データ型であるため、明示的に指定する必要はない).
引き続き上記の例を用いて、今回は構造関数Aを印刷して、どのように成長しているかを見てみましょう.
function A() {}   
var obj = new A(); 
console.dir(A); 

実際には、コンストラクション関数は通常の関数と変わらないが、用途(オブジェクトインスタンスを生成するために使用される)のため、コンストラクション関数の名前が付けられているだけだ.上図から、オブジェクト向けに関係のないプロパティ(arguments/caller/length/name)と、その関数役割ドメイン(Object())を省略します.残りはオブジェクト向けに密接に関係する2つのプロパティです.prototypeです.この__proto__は見覚えがあり、オブジェクトインスタンスobjにも登場しますが、ここではスキップしておきます.この__proto__属性についてお話しします.

コンストラクション関数のprototypeプロパティ


特に「コンストラクション関数のprototype属性」と明記されているのは、一般的な関数にとってprototype属性は意味がないからである.prototypeプロパティは、コンストラクション関数を使用して生成されたオブジェクトインスタンスがどのオブジェクトインスタンスを継承するかを指定します.上記のfunction A()のprototype属性がデフォルトのprototypeタイプのオブジェクトインスタンスを指すように(javascriptでは変数はオブジェクトインスタンスの参照にすぎないので、ここでは「指向」が比較的正確である)、function A()をコンストラクション関数としてインスタンス化したobjは、実際にはデフォルトのObjectタイプのオブジェクトインスタンスを継承しているが、obj自体にはカスタム属性/方法はないが、ただし、objによって継承されたすべての属性/メソッドを呼び出すことができます.

オブジェクト継承の一方向チェーンおぶじぇくとけいぞくの一方向チェーン:プロトタイプチェーンプロトタイプれんさ


コンストラクション関数のObjectプロパティが継承されたオブジェクトインスタンスを指定できる以上、このprototypeプロパティを変更して他のオブジェクトインスタンスを指すようにすれば、次のコードを参照してください.
var car = {    //     Object      
    status: 'stop'
}
function audi() {}    //    audi
audi.prototype = car;    //      audi prototype  ,    car
console.dir(audi);
var audiQ3 = new audi();    //      audi        audi     
console.dir(audiQ3);

まず、コンストラクション関数audiが印刷した結果を見てみましょう.
audiからprototype.statusはこの時のaudiを見ることができる.prototypeは確かにprototypeというオブジェクトのインスタンスを指しています.次に、修正したコンストラクション関数audiを用いて生成するオブジェクトインスタンスaudiQ 3を見る.
audiQ 3というインスタンスオブジェクトのデータ型は{status: 'stop'}(コンストラクション関数と同名)であることがわかります.また、audiQ 3の下にはaudiという唯一のメンバー属性しかありません.__proto__を引き続き見てみると、__proto__が入っています.そう、status: "stop"プロパティは、__proto__というオブジェクトインスタンスへの参照です.

プロトタイプチェーンの接点:{status:'stop'}


オブジェクトインスタンスの__proto__プロパティによって、継承されたオブジェクトインスタンスが継承されたオブジェクトインスタンスにリンクされ、ループがループされ、オブジェクトインスタンス、継承されたオブジェクトインスタンスへの参照からなるチェーン:プロトタイプチェーンが形成される.__proto__は、コンストラクション関数の__proto__属性によって決定される(prototypeprototypeに直接付与されるとも言える)ため、__proto__属性を修正することによって、このprototypeを操作することができる.

コンストラクション関数について


コンストラクション関数は、主にオブジェクトの作成時にオブジェクトを初期化するために使用されます.すなわち、オブジェクトメンバー変数に初期値を割り当てるために使用されます.では、javascriptのコンストラクション関数は、どのようにしてこのような機能を実現しますか.以下のDEMOを例として説明する.
function car() {    //       car     
    this.status = 'stop';    //     car                 status    ,     'stop'
    this.start = function() {    //           start     
        this.status = 'running';
    }
}
var audiQ3 = new car();    //  car        ,       audiQ3
console.dir(audiQ3);
audiQ3.start();    //  audiQ3 start  
console.dir(audiQ3);

まず構造関数carを見てみると、 が見えます.このthis.status = 'stop';はcarというfunctionを指していますか.いいえ、このthisは実際には現在の関数の実行時のコンテキスト環境を指し、関数を構築する際に使用されるのは新しく生成されたオブジェクトインスタンスを指します(本DEMOではaudiQ 3を指します).したがって,thisを利用すれば,コンストラクション関数において,将来このコンストラクション関数を利用して生成されるオブジェクトインスタンスにメンバ属性とメンバメソッドを追加することができる.

JAvascriptオリジナルサポートのプロトタイプ継承方法:this

Object.createは、原生のプロトタイプ継承方式を定義している:ECMAScript 5、私たちはこのような方法でプロトタイプ継承をより簡便に実現することができる.

構文


Object.create(proto, [ propertiesObject ])

パラメータ


protoは、新しく作成されたオブジェクトのプロトタイプとしてオブジェクトです.
propertiesObjectはオプションです.このパラメータ・オブジェクトは、新しく作成されたオブジェクトの属性名である属性と値のセットです.値は属性記述子です(これらの属性記述子の構造はObject.defineProperties()の2番目のパラメータと同じです).注意:このパラメータオブジェクトはundefinedではなく、オブジェクト自体が持つ列挙可能な属性のみが有効です.つまり、オブジェクトのプロトタイプチェーン上の属性は無効です.

var car = {
    status: 'stop',
    start: function() {
        this.status = 'running'
    }
}
var audiQ3 = Object.create(car);
console.dir(audiQ3);

どうすれば、Object.createという方法で簡単にプロトタイプ継承が実現できるのでしょうか.実際には、Object.createがパッケージを作ってくれました.
function (proto) {
  var constructor = function(){}
  constructor.prototype = proto;
  return new constructor();
}

ブラウザ互換性の修復

ECMAScript 5がIE上でECMAScript 5まで完全にサポートされていることを考慮して、低バージョンのIEブラウザを互換化する必要があります.実際には簡単です.上のコードを少し修正すればいいです.
if(typeof Object.create !== 'function') {
    Object.create = function(proto) {
      var constructor = function(){}
      constructor.prototype = proto;
      return new constructor();
    }
}