オブジェクトとプロトタイプに直面する(五)

4073 ワード

プロトタイプチェーンによる継承
あるオブジェクトを別のオブジェクトのプロトタイプに割り当てると、後者は前者のすべての属性とメソッドを継承します.
次のようになります.
function Parent(){
    this.age = 23424
}
function Child(){
}
var c = new Child()
alert(c.age) // undefined
Child.prototype = new Parent()
alert(c.age) // undefined

var d = new Child()
alert(d.age)  // 23424

最初にundefinedが現れたのは,Childにage属性が定義されていないためである.
オブジェクトを作成するとChildが作成されます.prototypeはc._に値を付与するproto__.cはChildプロトタイプを修正するより先に作成するのでChild.prototypeの再割り当てはc._に影響しません.proto__ オブジェクトを指すため、2番目のalertの場合、c.ageはundefinedのままです.
dはChildプロトタイプを修正した後に作成されるので、d.ageはParent関数でage属性を定義する値である.
欠点
  • は、継承された属性に対して異なる値を設定できません.属性はすべてのオブジェクトが共有しているため、1つのオブジェクトが値を変更すると、残りのオブジェクトの値も変更されます.
  • newオブジェクトの場合、属性に異なる値
  • を指定することはできません.
    オブジェクトを偽装して継承を実装するには
    オブジェクトダミーとは,サブクラスのコンストラクション関数で親コンストラクション関数を呼び出すcallメソッドである.
    次のようになります.
    function Parent(age){
        this.age = age
    }
    function Child(age){
        Parent.call(this,age) //           call   
    }
    Parent.prototype.sex = 'f'
    var c = new Child('1111')
    console.log(c.age)  //1111
    console.log(c.sex) // undefined
    

    callメソッドを呼び出すと、最初のパラメータthisはChildのインスタンスオブジェクトを表します.
    callメソッドを呼び出すと、ChildのオブジェクトにParentメソッドが呼び出されることになるので、ParentメソッドのthisはChildのインスタンスオブジェクトを表します.したがって、呼び出しが終了すると、Childのインスタンスオブジェクトにage属性が既に存在する.
    ただし,オブジェクトダミーメソッドを用いると,構造時にパラメータを渡すことができ,プロトタイプを用いないため共有の問題もある.
    欠点
  • 上記の例のように、オブジェクトの偽装は親プロトタイプのメソッド属性を子に継承させることができないため、多重化できません.これは、オブジェクトが単純にサブクラスオブジェクトに親のコンストラクション関数を呼び出し、親のコンストラクション関数によって子オブジェクトにいくつかの属性、メソッドを追加するだけで、親のプロトタイプとは何の関係もないためです.

  • オブジェクトの偽装+プロトタイプチェーン
    プロトタイプチェーンを使用すると、オブジェクトの偽装時の欠点を解決できます.
    次のようになります.
    function Parent(age){
        console.log('Parent()')
        this.age = age
    }
    Parent.prototype.sex = 'f'
    
    function Child(age){
        Parent.call(this,age)
    }
    Child.prototype=new Parent() 
    var c = new Child('cccc')
    console.log(c.sex+","+c.age) // f,cccc
    

    子クラスのプロトタイプオブジェクトを親クラスのオブジェクトに設定すると、親クラスのプロトタイプの属性、メソッドを継承できます.
    欠点
  • 親クラスのコンストラクション関数は2回実行されます.サブクラスに設定するために初めて使用されるプロトタイプオブジェクト.2回目にサブクラスが偽装された場合、サブクラス構築関数でcallメソッドが呼び出され、親クラス構築関数の再実行が発生します.

  • 一時中継関数の継承
    プロトタイプチェーンと同様に、プロトタイプチェーンのいくつかの操作を1つの関数にカプセル化するだけです.
    次のようになります.
    function create(o){
        function F(){}
        F.prototype=o;
        return new F();
    }
    
    var p = {
        age:324,
        sex:'m'
    }
    var o = create(p)
    console.log(o.sex)  //m
    

    欠点
    それ自体がプロトタイプチェーン継承の改良であるため、プロトタイプチェーン継承には欠点があり、それもある.
    スプリアス継承
    一時中継関数をファクトリメソッドと組み合わせると,寄生式継承である.
    次のようになります.
    function create(o){
        function F(){}
        F.prototype=o;
        return new F();
    }
    
    function obj(o){
        var r = create(o);
        r.run = function(){
            console.log(this.age+","+this.sex)
        }
        return r;
    }
    
    var p = {
        age:324,
        sex:'m'
    }
    
    var o = obj(p)
    o.run()
    

    objメソッドを追加するのは,新しいオブジェクトの拡張を統一的に処理するためである.
    6つ目の方法
    オブジェクトの偽装を使用して、構造関数に親が追加した属性、メソッドを継承します.プロトタイプ継承方式を使用して、親がプロトタイプに追加した属性、メソッドを継承します.
    次のようになります.
    function obj(obj) { 
        function F(){}
        F.prototype = obj;
        return new F()
    }
    function create(parent,child){
        var f = obj(parent.prototype) // f   parent       
        f.constructor= child; //    child     constructor    
        child.prototype = f; // child      f,   child      parent       、  
    }
    function Parent(age,num){
        this.age = age
        this.num = num;
    }
    
    Parent.prototype.run = function(){
        console.log('this is prototype\'s run --- '+this.age)
    }
    
    function Child(age,num){
        Parent.call(this,'age','33') //         ,                       、  
    }
    create(Parent,Child)
    
    var c = new Child()
    console.log(c.age+","+c.num) //             
    c.run() //              
    

    objメソッド:パラメータを継承するオブジェクトを返します.この方法の主な目的は,継承を実現する論理をカプセル化することである.外部で使用する場合は、継承をどのように実現するかを考慮することなく、このメソッドを呼び出すだけです.
    createメソッド:parentとchildの継承関係を確立します.外部にとって、主にcreateが呼び出されます.
    childコンストラクション関数:オブジェクトの偽装により、childオブジェクトがparentコンストラクション関数の属性を継承できるようにします.