JavaScriptの対象継承雑談

5764 ワード

本文は高級なプログラムに基づいて本の原型を設計し、章を受け継ぐ上でまとめたものです.ECMAScriptの継承を実現する主な方式はプロトタイプチェーンによるものです.基本思想は、原型を利用して一つの引用タイプに別の引用タイプの属性と方法を継承させることであり、対象の原型=継承対象の例であり、例の「Prototype」は継承対象の原型を指すので、継承対象の原型は継承対象の原型を指すことができる.
原型引継ぎ
高級なプログラムを借りて設計した本のコードは以下の通りです.
        function SuperType(){
            this.property = true;
        }
        
        SuperType.prototype.getSuperValue = function(){
            return this.property;
        };
        
        function SubType(){
            this.subproperty = false;
        }
        
        //inherit from SuperType
        SubType.prototype = new SuperType();
        
        SubType.prototype.getSubValue = function (){
            return this.subproperty;
        };
        
        var instance = new SubType();
        alert(instance.getSuperValue());   //true
 
ここではSubTypeのプロトタイプを変えて、その新しいプロトタイプをSuperTypeの例とします.そのため、新しいプロトタイプはSuperTypeのすべての属性と方法を持つだけでなく、内側のポインタがSuperTypeのプロトタイプを指しています.こうして相続の関係ができた.
インスタンスがあるコンストラクタに属するかどうかを決定します.
  • instance of
  • を使用します.
    alert(instance instanceof Object);      //true
    alert(instance instanceof SuperType);   //true
    alert(instance instanceof SubType);     //true
    
    実はinstance of原理は、インスタンスの__proto__とコンストラクションのprototypeが同じ参照かどうかを比較することにある.
    不足:プロトタイプチェーン上のすべての構造関数はインスタンスオブジェクトの構造関数として扱われ、instance ofはtrueに戻ります.だからinstance ofで判断すると、あるオブジェクトは特定の構造関数の例ではなく、プロトタイプチェーン上の他の関数である可能性があります.
    解決策:例の__proto__.constructorを使用して、コンストラクション名と比較して、より厳密にして、インスタンスのオブジェクトのコンストラクタを正確に導出することができる.
    instance.__proto__.constructor===Subtype //true
    instance.__proto__.constructor===SuperType//false
    instance.__proto__.constructor===Object//false
    
  • isProttypeOf()
  • を使用する.
      alert(Object.prototype.isPrototypeOf(instance));    //true
      alert(SuperType.prototype.isPrototypeOf(instance)); //true
      alert(SubType.prototype.isPrototypeOf(instance));   //true
    
    慎重に定義する方法
    サブタイプは、オーバータイプのいずれかの方法を書き換える必要がある場合があります.または、スーパータイプの中には存在しない方法を追加します.プロトタイプにメソッドを追加するコードは、プロトタイプを置き換える文の後に必ず入れます.プロトタイプチェーンによる継承は、オブジェクトの字面量を使ってプロトタイプを作成することができません.そうでないとプロトタイプチェーンを切断します.
    プロトタイプチェーンの問題
    その最大の問題は、参照タイプの値の継承について、すべてのインスタンスが参照タイプの指針を有しており、一例がこの参照タイプの値を書き換えると、この変更は直ちにすべてのインスタンスに適用されることである.また、サブタイプのインスタンスを作成する際には、超タイプの構造関数にパラメータを転送できません.
    コンストラクタ継承
    この継承法の中心は,サブタイプのコンストラクタの内部で超型コンストラクタを呼び出すことにある.
            function SuperType(){
                this.colors = ["red", "blue", "green"];
            }
            function SubType(){  
                //   SuperType      
                SuperType.call(this);
            }
            var instance1 = new SubType();
            instance1.colors.push("black");
            alert(instance1.colors);    //"red,blue,green,black"
            
            var instance2 = new SubType();
            alert(instance2.colors);    //"red,blue,green"
    
    SuperType.call(this)このステップは主に新しく作成されたSubTypeのインスタンスの環境でSuperTypeの構築関数を呼び出し、新しいSubTypeオブジェクト上でSuperType()関数で定義されたすべてのオブジェクト初期化コードを実行します.SubTypeの各インスタンスはそれぞれ独自の属性コードを持っています.
    グループ引継ぎ
    プロトタイプの継承と構造関数の継承を組み合わせると、プロトタイプ上の定義方法により関数多重化を実現することができ、また各インスタンスに独自の属性があることを保証することができる.
            function SuperType(name){
                this.name = name;
                this.colors = ["red", "blue", "green"];
            }
            
            SuperType.prototype.sayName = function(){
                alert(this.name);
            };
    
            function SubType(name, age){  
                SuperType.call(this, name);
                
                this.age = age;
            }
    
            SubType.prototype = new SuperType();
            
            SubType.prototype.sayAge = function(){
                alert(this.age);
            };
            
            var instance1 = new SubType("Nicholas", 29);
            instance1.colors.push("black");
            alert(instance1.colors);  //"red,blue,green,black"
            instance1.sayName();      //"Nicholas";
            instance1.sayAge();       //29
            
           
            var instance2 = new SubType("Greg", 27);
            alert(instance2.colors);  //"red,blue,green"
            instance2.sayName();      //"Greg";
            instance2.sayAge();       //27
    
    SuperTypeコンストラクターに属性を定義し、サージをサポートし、SuperTypeプロトタイプに方法を定義し、SubTypeコンストラクタにSuperTypeコンストラクタを呼び出します.
    組み合わせ継承の最大の欠点は,二次超構造関数を呼び出したことにある.
    寄生ユニット引き継ぎ
    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    //Object.create       
    function inheritPrototype(subType, superType){
        var prototype = Object.create(superType.prototype);   //create object
        prototype.constructor = subType;               //augment object
        subType.prototype = prototype;                 //assign object
    }
                            
    function SuperType(name){
        this.name = name;
        this.colors = ["red", "blue", "green"];
    }
    
    SuperType.prototype.sayName = function(){
        console.log(this.name);
    };
    
    function SubType(name, age){  
        SuperType.call(this, name);
        
        this.age = age;
    }
    
    inheritPrototype(SubType, SuperType);
    
    SubType.prototype.sayAge = function(){
        console.log(this.age);
    };
    
    var instance1 = new SubType("Nicholas", 29);
    instance1.colors.push("black");
    console.log(instance1.colors);  //"red,blue,green,black"
    instance1.sayName();      //"Nicholas";
    instance1.sayAge();       //29
    
    
    var instance2 = new SubType("Greg", 27);
    console.log(instance2.colors);  //"red,blue,green"
    instance2.sayName();      //"Greg";
    instance2.sayAge();       //27
    
    本と他の人のいくつかの文章を読んで、感じは継承の方式に対して一定の理解があって、すべての方法の書き方をも熟知することができて、しかしいつも文法を受け継いで実際の応用の中で使うのが多くないと感じて、今の業務性コードが書くのが多いためかもしれません.これらの知識は必ず使われます.