JavaScriptのパッケージと継承

15814 ワード

JavaScriptの「対象向けプログラミング」というと、主にパッケージと継承です.ここでは主に阮一峰と他のブログのシリーズ記事に基づいてまとめられています.
継承メカニズムの設計思想
  • すべてのインスタンスオブジェクトが共有したい属性と方法は、このオブジェクトの中に配置されます.それらは共有する必要がない属性と方法を、コンストラクタに入れます.
  • は、すべてのインスタンスオブジェクトが同じprototypeオブジェクトを共有するので、外部から見ると、prototypeオブジェクトはインスタンスオブジェクトのプロトタイプのように見えるが、インスタンスオブジェクトは「継承された」prototypeオブジェクトのように見える.
  • パッケージ
    主にどのように「パッケージ」データと方法を紹介し、どのように原型オブジェクトからインスタンスを生成しますか?
    (1)パッケージ:属性と方法を一つのオブジェクトにパッケージ化する.
    (2)どのようにある規格(原型)からオブジェクトを生成しますか?オリジナルの方法(文面で一つの手動でオブジェクトを生成する)と比較して、
  • コードの繰り返しを減らし、オブジェクトが一般的に持つ属性をまずコンストラクタで定義し、コンストラクタを使ってオブジェクトを生成するときに、パラメータを参照すれば、生成されるオブジェクトの属性の割り当てができます.
  • は、生成されたオブジェクトと原型オブジェクトとの間の関係を表している.
  • アーキテクチャー関数が持つprototype属性の利点:すべてのオブジェクトが持つ値が同じ属性をprototypeにかけ、いくつかのオブジェクトを生成するに関わらず、これらはこの1つのprototypeを共有し、メモリの中で1つだけで、不必要なリソースの浪費を減らす.isPrototypeOfhasOwnProperty()は、プロトタイプ属性を含むオブジェクトのすべての属性を巡回した、ローカル属性かプロトタイプ属性かを検出する.
  • 【注意】:構造関数の属性はローカル属性であり、各オブジェクトはそれぞれの値を維持し、inの属性は参照属性であり、全てのオブジェクトは一つの属性を共有している.プロトタイプの属性がインスタンス属性と同名の場合、プロトタイプの属性はインスタンス属性によって上書きされます.
    コンストラクタの継承(5つの方法)
    方法1:コンストラクタバインディング
    サブオブジェクト構造関数prototypeに行を追加します.
           
          
          
          
    1
           
          
          
          
    Animal.apply( this, arguments);
    利点:複数の相続が可能(Cat()複数のオブジェクト).また、サブクラスのインスタンスを作成すると、パラメータを親に渡すことができます.
    短所:親のタイプの例としての属性と方法だけを継承することができます.親のタイプのプロトタイプの属性/方法を継承することはできません.(ここでは、【組み合わせ相続】を示す.この方法に基づいて、方法2のプロトタイプ継承、すなわちcall/applycall方法を加えて、組み合わせ継承はプロトタイプ属性/方法を継承することができ、また実例的な属性/方法を継承することができ、また、参照することができる).
    方法2:prototypeモード(プロトタイプチェーン継承とも呼ばれるので、prototypeの修正が必要です.)
    親の例をサブタイプの原型とします.「猫」のプロトタイプの対象として、アニマルの例を指すなら、すべての「猫」の例は、アニマルを継承します.
           
          
          
          
    1
    2
           
          
          
          
    Cat.prototype = new Animal(); // prototype , 。 Cat.prototype.constructor Animal
    Cat.prototype.constructor = Cat; // ,
    【注意】:
  • のいずれかのconstructorオブジェクト(prototype)は、cat.prototype属性を有し、その構造関数を指す.
  • より重要なのは、各インスタンス(constructor)にもcat1属性があり、デフォルト呼び出しconstructorオブジェクトのprototype属性があることである.
  • =>
    【普適性のルール】constructorオブジェクトを置き換えると、次のステップは必ず新しいprototypeオブジェクトにprototype属性を加え、この属性を元の構成関数に戻す.
           
          
          
          
    1
    2
           
          
          
          
    o.prototype = {};
    o.prototype.constructor = o;
    短所:継承ができない;サブクラスのインスタンスを作成すると、親のコンストラクタにパスできません.
    方法3:直接引継ぎconstructor利点は、効率が比較的高い(prototypeの例を実行して確立する必要がない)ことであり、省メモリを比較することである.
    欠点は、AnimalおよびCat.prototypeが同一のオブジェクトを指している場合、Animal.prototypeに対する修正はいずれもCat.prototypeに反映される.
           
          
          
          
    1
    2
           
          
          
          
    Cat.prototype = Animal.prototype;
    Cat.prototype.constructor = Cat; // `Animal.prototype.const  JavaScript ructor` 。 。
    方法四:空の対象を仲介として利用する(寄生組み合わせの継承ともいう):完璧
           
          
          
          
    1
    2
    3
    4
    5
    6
    7
           
          
          
          
    function (Child, Parent) {
       var F = function(){};
      F.prototype = Parent.prototype;
      Child.prototype = new F();
      Child.prototype.constructor = Child;
      Child.uber = Parent.prototype; // , , ,
    }
    方法5:コピー相続:Animal.prototypeのすべての属性と方法をParent.prototypeにコピーする.
           
          
          
          
    1
    2
    3
    4
    5
    6
    7
    8
    9
           
          
          
          
    function (Child, Parent) {
    var p = Parent.prototype;
       var c = Child.prototype;
       for ( var i in p) {
        c[i] = p[i];
      }
      c.uber = p;
    }

    拷贝继承支持多继承。

    非构造函数的继承

    继承某个具体的对象。

    方法一:object()(实质上还是原型继承)

           
          
          
          
    1
    2
    3
    4
    5
           
          
          
          
    function object(o) {
       function F() {}
      F.prototype = o;
       return new F();
    }
    方法2:浅いコピー(データのみコピーできるのは基本タイプの対象)
    問題があります.親オブジェクトの属性が配列または他のオブジェクトに等しい場合、実際には、子オブジェクトが取得したのはメモリアドレスだけで、本物のコピーではなく、親オブジェクトが改竄される可能性があります.
    方法3:ディープコピー
    再帰的に浅いコピーを呼び出します.
           
          
          
          
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
           
          
          
          
    function deepCopy(p, c) {
    var c = c || {};
    for ( var i in p) {
    if ( typeof p[i] === 'object' ) {
    c[i] = (p[i].constructor === Array) ? [] : {};
    deepCopy(p[i], c[i]);
    } else {
    c[i] = p[i];
    }
    }
    return c;
    }
    長所:継承をサポートします.
    短所:効率が低く、メモリの占有率が高い(親の属性をコピーするため).親類の列挙できない方法を取得できませんでした.