先端面接基礎回顧の深化JS継承

5186 ワード

前言
柔軟なjsにとって、継承はjavaなどの言語に比べて、継承の実現方式は百花斉放と言える.方式の多様さは知識の多さを意味し、もちろん面接では避けられない点でもあります.ES 6 classを抜きにして、伝統的な継承方法は何種類知っていますか.それぞれの実現原理は何なのか、優劣を話してもいいですか.ここでは具体的な例を結びつけて、漸進的な考え方に従って継承の発展を見てみましょう.
の準備を
js継承については、jsインスタンス化オブジェクトの実装方法を先にレビューします.
コンストラクション関数とは、newによってオブジェクトをインスタンス化できる関数であり、オブジェクトインスタンスを毎回手動で宣言しないように多重化することを目的としています.
newは以下のように簡単に実現される.
function my_new(func){
    var obj = {}
    obj._proto_ = func.prototype //        ,   func   
    func.call(obj) //       
    return obj
}

以上から分かるように、コンストラクション関数呼び出しにより、インスタンス属性をターゲットオブジェクトに割り当てることができます.これにより、子クラスで親クラス構築関数を呼び出すことも継承の目的を達成できると考えられます.これはjs継承の構想を提供し,すなわち構造関数によって呼び出される.
プロトタイプ属性とは,プロトタイプ指向を修正することでプロトタイプ属性の共有を実現する.では、継承時も同様にこの方式で行うことができます.
まとめ
構造関数とプロトタイプチェーンの2つの特性に基づいてjs言語の柔軟性を結合する.継承の実現方式は多くの変化があってもその宗を離れない.
継承するn方式
プロトタイプ継承
定義:この継承は、プロトタイプを使用して既存のオブジェクトに基づいて新しいオブジェクトを作成し、カスタムタイプを作成することなくプロトタイプ継承と呼ばれます.
コードを直接見ると、より明確になります.
function createObj(o) {
  function F() { }
  F.prototype = o;
  return new F();
}
var parent = {
  name: 'trigkit4',
  arr: ['brother', 'sister', 'baba']
};
var child1 = createObj(parent);

この方式は表面的にはオブジェクトに基づいて作成され、構造関数は必要ありません(もちろん実際の構造関数はカプセル化されています).プロトタイプオブジェクトのみを使用するため、名前はプロトタイプ継承です.
欠点が明らかに優れている者
  • は継承を多重化できません.各サブクラスのインスタンスは、完全なcreateObjプロセスを実行します.
  • サブクラスオブジェクトは、コンストラクション関数のためにcreateObjにカプセル化されており、コンストラクション関数は存在しない.これにより、初期化できない場合にパラメータが伝達されます.補足:createObjは私たちのES 6でよく使われるObject.create()ですが、Object.createは改善されており、追加のパラメータで改善することができます.

  • 解決構想は構造関数がないことが問題を招いたと述べた以上,大胆な推測は,さらに構造関数のプロトタイプチェーン継承に関与している.
    プロトタイプチェーン継承
    定義:親の属性(メソッドも含む)を子に継承させるには、まずコンストラクション関数を定義する必要があります.次に、親クラスの新しいインスタンスをコンストラクション関数のプロトタイプに割り当てます.
    function Parent() {
      this.name = 'mike';
    }
    function Child() {
      this.age = 12;
    }
    Child.prototype = new Parent();
    child.prototype.contructor = child //        ,       。
    var child1 = new Child();

    すなわち,サブクラスのプロトタイプオブジェクトを直接修正することは,親構造関数のインスタンスを指し,親クラスのインスタンス属性とプロトタイプ属性を自分のプロトタイプチェーンに掛ける.
    欠点
  • Child.prototype=new Parent()では、サブ関数自体のプロトタイプ属性が上書きされ、必要に応じて後で補足されます.
  • サブオブジェクトがインスタンス化されている場合、親コンストラクション関数にパラメータを渡すことはできません.例えばnew Child()が実行される場合、nameを上書きするには、Child.prototype=new Parent()の場合のみです.我々がnew Child()の時に統一的なパラメータの初期化がより一般的な需要である.

  • サブクラスの初期化時に親コンストラクション関数を呼び出す方法を解決します.前の基礎を結びつけると、答えも出てくる.
    コンストラクタの借用(クラス継承)
    クラス継承:サブタイプコンストラクション関数の内部でスーパータイプを呼び出すコンストラクション関数です.
    考え方がはっきりしていて、問題によって駆動されます.プロトタイプチェーンサブクラスが親クラスにパラメータを伝達できないという問題がある以上、サブクラスの初期化が親クラスを呼び出すことで目的を満たすわけではない.
    例は次のとおりです.
    function Parent(age) {
      this.name = ['mike', 'jack', 'smith'];
      this.age = age;
    }
    Parent.prototype.run = function () {
      return this.name + ' are both' + this.age;
    };
    function Child(age) {
      //     
      Parent.call(this, age);
    }
    var child1 = new Child(21);

    これにより,初期化時のパラメータ伝達のニーズを満たすが,問題も顕著である.
    child1.run //undefined

    に質問
  • 親プロトタイプ属性損失親初期化はサンプル属性のみを継承し、プロトタイプ属性は子のプロトタイプチェーンで
  • を失う.
    考え方の喪失を解決する原因は,プロトタイプチェーンが指向を修正していないため,指向を修正すればよいのではないか.
    グループ継承
    定義:プロトタイプチェーンを使用してプロトタイプ属性とメソッドの継承を実現し、コンストラクション関数を借りてインスタンス属性の継承を実現します.
    例:
    function Parent(age) {
      this.name = ['mike', 'jack', 'smith'];
      this.age = age;
    }
    Parent.prototype.run = function () {
      return this.name + ' are both' + this.age;
    };
    function Child(age) {
      //         
      Parent.call(this, age);
    }
    Child.prototype = new Parent();//      
    Child.prototype.contructor = Child
    var child1 = new Child(21);

    これで問題は回避されます.
    child1.run() // "mike,jack,smith are both21"

    問題の機能が満たされたら、パフォーマンスに注目しましょう.この継承方式の問題は,親構造関数が2回実行されたことである.それぞれ:
    function Child(age) {
      //         ,   
      Parent.call(this, age);
    }
    Child.prototype = new Parent();//       ,   

    解決構想解決は自然に1回の構造関数呼び出しをキャンセルし、自然をキャンセルするにはこの2回の実行を分析し、機能的に重複しているかどうかを分析しなければならない.1回目はインスタンスとプロトタイプのプロパティを継承し、2回目は親クラスのインスタンスのプロパティを継承します.したがって、2回目は親パラメータの取得不可能性を満たすため、親コンストラクション関数を最初に呼び出さずにプロトタイプ属性のみを継承できるかどうかを考えるしかありません.答えは自然にできるが、前の原型式の継承はこの考えだ.
    スプリアスコンビネーション継承
    寄生とは,その名の通り,プロトタイプ属性を継承する方法を特定の方法にカプセル化し,構造関数の継承を組み合わせてプロトタイプ継承の不足を補うことを指す.
    ちょっと勘弁して、直接見ます.
    function createObj(o) {
      function F() { }
      F.prototype = o;
      return new F();
    }
    //             
    function create(parent, child) { 
      var f = createObj(parent.prototype);//      
      child.prototype = f
      child.prototype.constructor = child;//      ,     constructor  
    }
    
    function Parent(name) {
      this.name = name;
      this.arr = ['brother', 'sister', 'parents'];
    }
    Parent.prototype.run = function () {
      return this.name;
    };
    function Child(name, age) {
      //     
      Parent.call(this, name);
      this.age = age;
    }
    //              
    create(Parent.prototype,Child);
    var child1 = new Child('trigkit4', 21);

    このように問題を発見して問題を解決する構想に沿って相対的に完備した継承方式まで.ESの方式については本編では触れない.
    終わりの言葉
    厚い积み重ねてこそ、薄い髪ができる.好きなofferがほしいなら、余裕を持って基础を固めなければならない.新しい日にflagを立てないで、毎週3つの知識点で振り返ります.あなたが蝶を咲かせたら、自分で来ると信じてください.