理解JavaScript继承(二)

理解JavaScript继承(二)

5.寄生式继承

function object(o) {
    function F() {}    
    F.prototype = o;  
    return new F();
}

function createAnother(original){
  var clone = object(original);//通过调用函数创建一个新对象
  clone.sayHi=function(){//以某种方式增强这个对象
    alert("hi");
  };
  return clone;//返回这个对象
}

var person={
  name:"Nicholas",
  friends:["Shelby","Court,"Van"]
};

var anotherPerson=createAnother(person);
anotherPerson.sayHi();//"hi"

这个实例基于person返回了一个新对象anotherPerson。新对象不仅具有person的所有属性和方法,而且还有自己的sayHi()方法。

缺点:和构造函数一样,不能做到函数复用而降低效率。

6.寄生组合式继承

前面介绍说组合继承是JavaScript最常用的继承模式;实际上,它也存在一些问题,组合继承的最大问题是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。

组合式继承实例

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);//第二次调用SuperType()
            
    this.age = age;
}

SubType.prototype = new SuperType();//第一次调用SuperType()
        
SubType.prototype.sayAge = function(){
    alert(this.age);
};

在第一次调用SuperType()构造函数时,SubType.prototype会得到两个属性:name和colors;他们都是SuperType的实例属性,只不过现在位于SubType的原型中。当调用SubType构造函数时,又会调用一次SuperType构造函数,这一次又在新对象上创建了实例属性name和colors,于是,这两个属性就屏蔽了原型中的两个同名属性。

上面一共有两组name和colors属性:一组在实例上,一组在SubType原型中。这就是调用两次SuperType的结果。

为了解决这种情况,于是就出现了下面的——寄生组合式继承方法。

所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。(之所以是超类型的副本,而不是直接是超类型,如果直接是超类型的话。当子类型为原型添加方法时,也会影响到超类型的)

寄生组合式继承

function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}
    
function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype);   //创建对象
    prototype.constructor = subType;               //增强对象
    subType.prototype = prototype;                 //指定对象
}
                                
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;
}

inheritPrototype(SubType, 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.call(this, name);这调用了一次构造函数,并且因此避免了在prototype上面创建不必要的,多余的属性。

注:YUI的extend()就是采用这种寄生组合式继承

posted @ 2017-01-26 06:43  叶子陪你玩  阅读(156)  评论(0编辑  收藏  举报