JavaScriptの継承の深い理解を達成するための7つの方法

継承する1.プロトタイプチェーン

コア:プロトタイプのサブクラスとして親クラスのインスタンス

まず、コンストラクタとプロトタイプの例の間の関係を知るために:コンストラクタは、プロトタイプオブジェクトを有する、プロトタイプオブジェクトはコンストラクタを指すポインタを含む、インスタンスは、プロトタイプオブジェクトへのポインタを含みます。

機能父(){
     この .nameの= '親クラスの名前' ; 
}    
Father.prototype.getFatherName = 関数(){ 
    にconsole.log( '親クラス' ); 
} 

関数ソン(){
     この .nameの= 'サブクラスの名前; 
} 
// この時点で息子プロトタイプオブジェクトのメソッドやプロパティがある場合は、以下のSon.prototype =新しい父は()、プロトタイプのリダイレクト以来、プロトタイプのメソッドとプロパティが失われます 
Son.prototype.getAgeを= 関数(){ 
    にconsole.log(「年齢サブクラス」
} 

Son.prototype = 新しい新しい父親(); // コア:親クラス、インスタンスのインスタンスを作成し、プロトタイプサブクラスに割り当て

Son.prototype。 getSonName= 関数(){ 
    はconsole.log( 'メソッドサブクラス' ); 
} 

VAR息子= 新しい新しい息子(); 
son.getFatherName(); // 親クラス 
。Son.prototype .__プロト__ getFatherName = 機能(){ @ 欠点:親クラスのプロトタイプのインスタンスが複数ある場合、それぞれ影響します 
    はconsole.log(「親クラスの変更のサブクラス方法」); 
} 
son.getFatherName(); // 親クラスの変更のサブクラスを

短所:

 
  
  1. この親宣言されたプロパティ(パブリック属性およびプライベート属性)複数のインスタンス間で相互に影響を与える参照データ型の操作のすべてのインスタンスで共有されているを使用してください。

  2. あなたは、サブクラスのインスタンスを作成するときは、親クラスのコンストラクタにパラメータを渡すことはできません。

 
  

2.ボローコンストラクタ継承(コール)

 
  

コア:、強化された親クラスのコンストラクタサブクラスのインスタンスを使用して、すなわち、親クラスのインスタンスの属性は、サブクラスをコピー

機能父(名前、年齢){
     この .nameの= 名前;
    この .age = 年齢; 
}   
Father.prototype.getFatherName = 関数(){ 
    にconsole.log( '父类的方法' )。
} 

関数息子(名前、年齢、ジョブ){ 
    Father.call(この、名前、年齢)。// 继承自父
    この .JOB = 仕事。
} 
VARの息子= 新しい子( 'ジャッキー'、22 '前端开发' )。
// son.getFatherName(); //キャッチされない例外TypeError:son.getFatherNameは関数ではありません

 

利点:

  1. あなたは親にパラメータを渡すだけでなく、プロトタイプチェーンの継承を解決することができます:クラスのプロパティは、このプロパティを使用して宣言した親は、問題のすべてのインスタンス間で共有されます。

短所:

  1. 唯一の継承親クラスは、このプロパティ/メソッドによって宣言された親クラスのプロトタイプの継承プロパティ/メソッドをすることはできません。
  2. 親クラスの機能のサブクラスのすべてのインスタンスが定義された親クラスでこれを宣言し、再び実行しなければならないので、親クラスのメソッドを再利用することはできません。

3.継承の組み合わせ

コア:コンストラクタインスタンス属性の継承借り技術を使用して、2つの方法、プロトタイププロトタイプチェーンのメソッドとプロパティの継承の組み合わせ。

関数父(名前、年齢){
     この .nameの= 名;
     この .age = 年齢;
     この .sex = '人' ; 
} 
Father.prototype.getFatherName = 関数(){ 
    にconsole.log( '親プロセス' 
} 

関数の息子(名前、年齢、職業){ 
    Father.call(これは、名前、年齢); // 2番目の呼び出し:サブタイプのインスタンスを作成し
    、この .JOB = ジョブ; 
} 
Son.prototype = 新しい新しい父() ; // 最初の呼び出し:セットのサブタイプのプロトタイプのインスタンス際 
Son.prototype.constructor =息子; //バックそれらのプロトタイプコンストラクタを指す

VARソン= 新しい新しい子( 'ジャッキー'、22 'は、フロントエンド開発'である); 
son.getFatherName(); 
にconsole.log(SON)

利点:

  1. 親クラスのプロトタイプのプロパティを継承することができ、パラメータは、再利用可能な転送することができます。
  2. それぞれの新しいクラスのオブジェクトインスタンスのコンストラクタのプロパティは、プライベート導入されます。

短所:

  1. 親機能(新fatherFn()とfatherFn.call(本))には、2つの呼び出しは、いくつかのパフォーマンスの低下を引き起こします。
  2. オブジェクトサブクラスのインスタンスを作成する際に、プロトタイプが同じ2つのプロパティ/メソッドであろうという問題があります。

展開します。

コンストラクタの役割

Objectコンストラクタ参照のインスタンスを作成するために戻ります。

オブジェクトの我々は唯一のインスタンスは、コンストラクタの参照を持っていない場合:いくつかのシーンでは、我々は、インスタンスのためのインポートおよびエクスポートするオブジェクトのいくつかのラウンドを経てい、私たちは関数が外に例を構築またはコンストラクタインスタンスを追跡することであるからかわからない、より困難です。> - (それは、1ケースの間違ったのを防ぐために主であるあなたが明示的に、私は関数インスタンスが出てインスタンス化されるのか分からない例えばコンストラクタを使用しなければならないことですが、私はクローンが、その後、あなたが行うことができますしたいですinstance.constructor)今回は、オブジェクトインスタンスのコンストラクタプロパティのコンストラクタを参照することによって得ることができます

インスタンス=新しいsonFn()//インスタンス化可能サブクラスましょう
;輸出インスタンスを
非常に面倒なsonFnトラックで、その結果、// +輸出インポート複数のラウンドを、またはsonFnファイルに再導入する必要はありません
しましょうFN = instance.constructor
 

毎回ので、書き換え関数プロトタイプコンストラクタは、読み取りコンストラクタポイントの一貫性を維持するためには、その点を修正する必要があります

継承4.プロトタイプ式(Object.create())

コア:仲介者としてのヌルオブジェクトの使用は、直接空のプロトタイプオブジェクトのコンストラクタにオブジェクトを代入して、呼び出し元の関数に戻り、この機能は、プロパティまたはオブジェクトのインスタンスを追加して自由になりました。

 
  
/ * 原則のObject.create()の実装* / 
// CLONEOBJECT()シャローコピーを実行するには、コンストラクタFプロトタイプオブジェクトに直接渡さへの着信オブジェクト。
関数CLONEOBJECT(OBJ){
   関数F(){} 
  F.prototype = OBJ; // 入ってくるオブジェクトがプロトタイプ空の関数として渡さOBJ 
  戻り 新しい新しい F.を(); // このオブジェクトのプロトタイプオブジェクトを継承され、プロトタイプチェーン検索オブジェクト属性を継承得ることができる
} 

VAR父= { 
    名: 'ジャッキー' 
    年齢: 22であり
    コース:[ 'フロントエンド' ] 
} 

// VAR = SON1 Object.create(父); //同じ効果
VAR = SON1 CLONEOBJECT(父)。 
son1.courses.push('リア' ); 

VAR son2 = CLONEOBJECT(父); 
son2.courses.push( 'フルスタック' ); 

にconsole.log(father.courses); //   [ "フロントエンド"、 "後"、「フルスタック「]
 
  

利点:

既存のオブジェクトから派生した新しいオブジェクトは、カスタム型を作成する必要はありません

短所:

継承するプロトタイプチェーンのように。継承する共有オブジェクトのプロパティの複数のインスタンスは、であり、改ざんされてもよい、パラメータを渡すことができません。

5.寄生継承

コア:式のプロトタイプに継承、連続をパッケージ化するためのプロセスを作成するための唯一の機能、増強オブジェクト(いくつかの新しいメソッドとプロパティを追加しました)の中にいくつかのフォームを行うための機能、そして最終的にオブジェクトを返します。

使用シナリオは:特にいくつかの固定方法を行うことを目標と強化します。

関数createAnother(OBJ){
     VARのクローン= Object.create(OBJ); 
    clone.skill = 関数(){   // このオブジェクトを強化するいくつかの方法 
        はconsole.log( 'RUN' ); 
    }; 
    戻りクローン; 
} 

VAR =動物{ 
    EAT: '食品' 
    飲料: '水' 
} 

VAR犬= createAnother(動物); 
dog.skillを();

 

長所:それは、特定のプロパティのみ設定されているので、カスタム型を作成していないが強化され、オブジェクトの目的を達成するために、メソッドがオブジェクトを返す/シェルを増加しました

短所:

プロトタイプと、継承された:参照タイプ属性の同じポイントの複数のインスタンスが、プロトタイプ継承チェーン、パラメータを渡すことができない、とが改ざんされてもよいです

6.寄生複合継承

コア:借入コンストラクタの組み合わせ渡すパラメータと継承の寄生モード

  1. コンストラクタ(コール)属性/メソッドを借りて、この宣言を継承する親クラス
  2. プロトタイプチェーンを通して継承方法           

 

関数父(名前、年齢){
     この .nameの= 名;
     この .age = 年齢; 
} 
Father.prototype.getFatherName = 関数(){ 
    にconsole.log( '親クラス' 
} 

関数息子(名前、年齢、ジョブ){ 
    Father.call(これは、名前、年齢); // ボロー構成継承:サブクラスのインスタンスに親クラスから継承されたプロパティは、この方法で宣言された属性と
    、この .JOB = ジョブ; 
} 

// 寄生継承:パッケージson.prototypeオブジェクトのプロトタイプスタイルプロセスfather.prototypeの継承、および入ってくるオブジェクトを強化します。
関数inheritPrototype(息子、父){
     VARのクローン= Object.create(father.prototype)。// 原型継承:浅いコピーfather.prototypeは、オブジェクト 
    clone.constructor =息子を;   // 強化されたオブジェクトは、デフォルトコンストラクタのプロパティ書き換えプロトタイプの損失を補う 
    son.prototype =クローン; // 指定されたオブジェクトは、新しく作成されましたプロトタイプオブジェクトはサブクラスに割り当てられ
} 
inheritPrototype(息子、父親); // 点の親クラスプロトタイプサブクラスに

// 新しいサブクラスプロトタイプ特性 
Son.prototype.getSonName = 関数(){ 
    にconsole.log(「サブクラス方法' 
} 

VARソン= 新しい新しい子('ジャッキーフロントエンド開発' ' 22は、ある' ); 
にconsole.log(SON)。
  • 組成物に対して寄生モジュラー連続継承以下の利点を有します。
  1. 父は、親のコンストラクタ一度と呼ばれます。あなたはプロトタイプのサブクラスを指定し、コンストラクタを呼び出す必要がありますが、Father.prototypeへSon.prototype間接的なアクセスをさせてください。
  2. 子クラスのプロトタイプに不要な過剰プロパティを作成しないでください。式継承プロトタイププロトタイプ親クラス、プロトタイプチェーンコンテキストは不変に維持し、isPrototypeOfのinstanceof()が正常に使用することができます。3.組み合わせ寄生継承は、それが今では、多くのJSライブラリの用途の継承方式は、それが最も一般的な継承されたメソッドで、ほとんどが継承されたメソッドを成熟です。

短所:

後に主張し、それから、それはinheritPrototype()メソッドを置くようにしてください、プロパティとメソッドを追加するサブクラスプロトタイプにあります

 

7.ES6は継承(最良の方法)を拡張#を

コア:キーワードで実装の継承を明確かつ簡単なクラス、間に延びています。クラスは単なる糖衣構文で、その核となるアイデアは、まだ寄生複合遺産です。

父親{クラス
  コンストラクタ(名前、年齢){ 
    この .nameの= 名;
     この .age = 年齢; 
  } 
  スキル(){ 
    にconsole.log( '親クラススキル' ); 
  } 
} 

クラス延び父息子{ 
  コンストラクタ(名前、年齢、職業){ 
    スーパー(名前、年齢); // 唯一のスーパー呼び出した後に、このキーワードを使用することができ、スーパークラスのコンストラクタを呼び出す
    この .JOB = 仕事を; 
  } 

  GETINFO(){ 
    はconsole.log(この .nameの、この .age、この.JOB); 
  } 
} 


ましょう息子 = 新新息子( 'ジャッキー'、22、 ' フロントエンド開発' ); 
son.skill(); // スキル親クラス 
son.getInfo(); // ジャッキー・22は、フロントエンドの開発であります
  • 子クラスは、次のように、デフォルトで含まれるコンストラクタメソッドを定義していない場合。換言すれば、明示的に定義されたか否かにかかわらず、任意のサブクラスは、コンストラクタメソッドを有します。

サブクラスは、新しいインスタンスを作成するときに、それ以外の場合はエラーになり、コンストラクタメソッドでスーパーメソッドを呼び出す必要があります。独自のサブクラスは、このオブジェクトは、その処理、その後、親クラスの同じプロパティとメソッドの例を与えるために、親クラスのコンストラクタを成形することにより終了し、プラス独自のサブクラスのインスタンスの属性とメソッドする必要があるためです。あなたはスーパーメソッドを呼び出さない場合は、サブクラスは、このオブジェクトを取得することはありません。

ES5およびES6は継承された差異を継承した

  1. ES5継承は、親クラスのメソッドがこの(Father.call(本))に添加し、サブクラスのインスタンスを作成するために本質的です。
  2. 継承ES6は、最初にこのオブジェクトのインスタンスを作成し、次いで、サブクラスコンストラクタはこれを変更し、親クラスです。
  3. サブクラスは、このオブジェクトを所有していないので、最初に親クラスのスーパー()メソッドを呼び出す必要があります。

 

ナゲッツコミュニティのコンテンツ転送JackySummer、元のリンク    https://juejin.im/post/5dd55918e51d4536db238a19を

 

おすすめ

転載: www.cnblogs.com/yetiezhu/p/12093055.html