あなたがその時点でいくつかの知識を本当に理解できないなら、あなたはそれを当面に手放すことができ、それを未来に任せることができ、おそらくあなたはそれを理解することができます。
数ヶ月前、私は「JavaScript Advancedプログラミング(第3版)」を保持していましたが、オブジェクトの作成を噛んだ後、継承を噛み始めました。しかし、プロトタイプチェーンを噛んだ後、私はもうそれを我慢できず、私の心がますます乱雑になったので、私はそれを捨てて後者を見続けました。この夏休みを使用してこの相続財産を理解したので、メモを整理します。
プロトタイプチェーン
最初に記事を読みましょう。この記事の著者は非常に優れており、高解像度の写真が装備されています。笑…
リンク:[研究メモ]小さな観点からJSプロトタイプチェーンを見る
元のテキストからのいくつかの単語
プロトタイプとインスタンスの関係を決定します
プロトタイプとインスタンスの関係を検出するには、次の2つの方法があります。
instanceOf:オブジェクトが別のオブジェクトのインスタンスであるかどうかを判断します
InstanceOFの内部コンピューティングメカニズムは次のとおりです。
functioninstance_of(l、r){// l左式を表し、rは右式varo = r.prototype; // r l = l .__ proto__の表示プロトタイプを取得します。 //(true){if(l === null)returnfalse; if(o === l)//ここでポイント:oがlに厳密に等しい場合、truereturntrueを返します。 l = l .__ proto__; }}上記のコードは次のような抜粋です:javascriptインスタンスオフオペレーターの詳細な分析
ISPrototypeof():別のオブジェクトのプロトタイプチェーンにオブジェクトが存在するかどうかをテストします
これら2つの方法の違いを参照してください:JavaScript ISPrototypeof vs Instanceof Usage
プロトタイプチェーンのみを使用して継承を実現します
短所:1。タイプ値を参照するプロトタイプ属性は、インスタンスによって共有されます。 2。サブタイプのインスタンスを作成する場合、パラメーターをSuperTypeコンストラクターに渡すことはできません。
functionfather(){this.name = "father"; this.friends = ['aaa'、 'bbb'];} functionson(){} son.prototype = newfather(); son.prototype.constructor = son; vars1 = newson(); vars2 = newson(); console.log(s1.name); fatherconsole.log(s2.name); // fathers1.name = "son"; console.log(s1.name); // sonconsole.log(s2.name); // fatherconsole.log(s1.friends); // ["aaa"、 "bb"] console.log(s2.friend); "bbb"] s1.friends.push( 'ccc'、 'ddd'); console.log(s1.friends); // ["aaa"、 "bbb"、 "ccc"、 "ddd"] console.log(s2.friends); // ["aaa"、 "bbb"、 "ccc"、 "ddd"]コンストラクターを使用して継承を実現します
実装方法:サブタイプコンストラクター内のSuperTypeコンストラクターを呼び出します(Apply()およびcall()メソッドを使用)
利点:プロトタイプでタイプの属性を参照する問題を解決し、サブクラスはパラメーターをスーパークラスに渡すことができます
短所:サブクラスインスタンスは、親クラス(スーパークラス)のプロトタイプで定義されているメソッドにアクセスできないため、関数の再利用について話す方法はありません。
functionfather(name、friends){this.name = name; this.friends = friends;} phather.prototype.getname = function(){returnthis.name;}; functionson(// note:father constructiontorが息子の構成要素のプロパティを覆さないようにするfather.call(this、name、['aaa'、 'bbb']); this.age = 22;} vars1 = newson( 'son1'); newson( 'son2'); console.log(s1.name); // son1console.log(s2.name); //////// son2s1.friends.push( 'ccc'、 'ddd'); console.log(s1.friends); // ["aaa"、 "bbb"、 "ccc"、 "ddd"] console.log(s2.friends); // ["aaa"、 "bbb"] // typeRror:s1.getNameはfunctions2.getname(); // typeRror:s2.getNameは関数ではありません組み合わせ継承
実装方法:プロトタイプチェーンを使用して、プロトタイプの特性と方法の継承を実装し、コンストラクターを使用してインスタンスプロパティの継承を実装します。
functionfather(name、friends){this.name = name; this.friends = friends;} phather.prototype.money = "100k $"; father.prototype.getname = function(){console.log(this.name);}; futctionson(name、age){//親クラスの財産を継承しますfather.call(this、name、['aaa'、 'bbb']); this.age = age;} //親クラスのプロトタイプのプロパティとメソッドを継承するson.prototype = newfather(); son.prototype.constructor = son.son.prototype.getage = function(){console.log(this.age); = Newson( 'Son1'、12); s1.friends.push( 'ccc'); console.log(s1.friends); // ["aaa"、 "bbb"、 "ccc"] console.log(s1.money); // 100k $ s1.getname(); // son1s1.getage(); // 12vars2 = newson( 'son2'、24); console.log(s2.friends); // ["aaa"、 "bbb"] console.log(s2.money); // 100k $ s2.getname(); // son2s2.getage(); // 24併用継承は、プロトタイプチェーンまたはコンストラクターを使用して継承を実装し、その利点を組み合わせて、JavaScriptで最も一般的に使用される継承モデルになることを一方的に使用して、一方的に使用される欠陥を回避しますが、欠陥があり、組み合わせ継承の欠陥は後で特異的に言及されます。
プロトタイプの継承
実装のアイデア:プロトタイプを使用して、既存のオブジェクトに基づいて新しいオブジェクトを作成しますが、このためカスタムタイプを作成しません。
これを達成するために、次の関数(OBJ)が導入されます
functionobj(o){functionf(){} f.prototype = o; returnnewf();} varperson1 = {name: "percy"、friends:['aaa'、 'bbb']}; varperson2 = obj(person1); person2.name = "zyj"; person2.friends.push( 'ccc'); console.log(person1.name); // percyconsole.log(person2.name); // zyjconsole.log(person1.friends); // ["aaa"、 "bbb"、 "ccc"] console.log(person2.friend "" a "a" a "a" a "a sccc" "ccc"] ecmascript 5は、object.create()メソッドを追加することにより、プロトタイプ継承を正常化します。パラメーターを渡す場合、object.create()およびobj()メソッドは同じように動作します。 varperson1 = {name: "percy"、friends:['aaa'、 'bbb']}; varperson2 = object.create(person1); person2.name = "zyj"; person2.friends.push( 'ccc'); console.log(person1.name); zyjconsole.log(person1.friends); // ["aaa"、 "bbb"、 "ccc"] console.log(person2.friends); // ["aaa"、 "bbb"、 "ccc"]]この継承は、コンストラクターを動員して作成する必要がない場合に選択できますが、1つのオブジェクトを別のオブジェクトに類似したままにしたいだけです。
寄生性継承
寄生性継承は、プロトタイプの継承に密接に関連するアイデアです。
実装のアイデア:継承プロセスをカプセル化するためにのみ使用される関数を作成し、何らかの方法でオブジェクトを内部的に強化し、最終的にオブジェクトを返します。
functionobj(o){functionf(){} f.prototype = o; returnNewf();} functionCreateperson(original){// canksulate enternitance process varclone = obj(original); // create object clone.showsomething = function(){// endance object console.log( "hello world!"); }; returnclone; // return object} varperson = {name: "percy"}; varperson1 = createperson(person); console.log(person1.name); // percyperson1.showsomething(); // こんにちは世界!寄生的な組み合わせ継承
まず、以前の組み合わせ継承の欠点について話しましょう。組み合わせ継承の最大の問題は、状況が何であれ、親クラスのコンストラクターが2回呼び出されることです。1つはサブクラスのプロトタイプを作成するときであり、もう1つはサブクラスコンストラクターを呼び出すとき、親クラスのコンストラクターはサブクラスコンストラクター内で呼ばれます。
functionfather(name、friends){this.name = name; this.friends = friends;} phather.prototype.money = "100k $"; father.prototype.getname = function(){console.log(this.name);}; futctionson(name、age){//親クラスの財産を継承しますfather.call(this、name、['aaa'、 'bbb']); // father()への2番目の呼び出しは実際にはthis.age = age;} //親クラスのプロトタイプのプロパティとメソッドを継承しますson.prototype = newfather();最初の呼び出しは、サブクラスのプロトタイプを親クラスのインスタンスにし、サブクラスのプロトタイプが親クラスのインスタンス属性を取得するようにします。 2番目の呼び出しにより、サブクラスのインスタンス属性が親クラスのインスタンス属性も取得されます。また、サブクラスのインスタンス属性は、デフォルトでサブクラスプロトタイプで複製された属性をブロックします。したがって、これら2つの呼び出しの後、サブクラスのプロトタイプに不必要な属性が表示されるため、この問題を解決するために寄生的な組み合わせ継承が導入されます。
寄生的な組み合わせ継承の背後にあるアイデアは、サブクラスのプロトタイプを指定するために親クラスコンストラクターに電話する必要はありません。必要なのは、親クラスのプロトタイプのコピーだけです。
基本的に、寄生性継承を使用して親クラスのプロトタイプを継承し、結果を子クラスのプロトタイプに戻すことです。
functionobj(o){functionf(){} f.prototype = o; returnnewf();} functioninheritprototype(son、父){varprototype = obj(father.prototype); // create object prototype.constuctor = son; // Object Son.Prototype = Prototype; // return object} functionfather(name、friends){this.name = name; this.friends = friends;} father.prototype.money = "100k $"; father.prototype.getName = function(){console.log(this.name);}; fuctionson(name、age){//親会社の財産の継承{// father.call(this、name、['aaa'、 'bbb']); this.age = age;} //親クラスのプロトタイプのプロパティとメソッドを継承する継承プロトタイプ(son、父); son.prototype.getage = function(){console.log(this.age);}; vars1 = newson( 'son1'、12); s1.friends.push( 'ccccc'); console.log( 'ccccc'); "BBB"、 "ccc"] console.log(s1.money); // 100k $ s1.getname(); // son1s1.getage(); // 12vars2 = newson( 'son2'、24); console.log(s2.friends); // ["aaa"、 "bbb"] console.log(s2.money); // 100k $ s2.getname(); // son2s2.getage(); // 24利点:サブクラスのプロトタイプに、親クラスで不必要なインスタンスプロパティを継承しないようにします。
開発者は一般に、寄生的な組み合わせ継承が型継承に基づいた最も理想的な継承方法であると考えています。
やっと
最後に、2つの非常に難しい記事を強くお勧めします
JavaScriptプロトタイプの継承が実際にどのように機能するか
JavaScriptの擬似古典的継承図(壁を越える必要がある)
2番目の記事から難しい写真を撮ります。
それを読んだ後、私は数秒でプロトタイプチェーンを理解しています。何かありますか?
上記は、JavaScriptによって継承された情報のコレクションです。今後も関連情報を追加し続けます。このウェブサイトへのご支援ありがとうございます!