JavaScript中继承的主要方法

 

1. 原型链继承

子类使用基类对象重写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();
        
        //new method
        SubType.prototype.getSubValue = function (){
            return this.subproperty;
        };
        
        //override existing method
        SubType.prototype.getSuperValue = function (){
            return false;
        };
        
        var instance = new SubType();
        alert(instance.getSuperValue());   //false

 

主要缺点: 通过原型来继承时, 原型会变成另一个类型的实例, 所以, 原先实例属性被变成了子类中的原型属性.

2. 借用构造函数 

子类中使用call/apply调用基类构造函数方法

function SuperType(name){
    this.name = name;
}

function SubType(){  
    //inherit from SuperType passing in an argument
    SuperType.call(this, "Nicholas");
    
    //instance property
    this.age = 29;
}

var instance = new SubType();
alert(instance.name);    //"Nicholas";
alert(instance.age);     //29

缺点: 并非真正的继承, 无法执行基类中原型的方法.

3. 组合继承(伪经典继承)

既执行借用构造函数, 又执行原型链传递, 是最常用的继承方式.

其最大问题是 无论什么情况下,都会调用两次超类型的构造函数.

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

 4. 原型式继承

思路是借用原型来基于已有的对象创建新对象.

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

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

var anotherPerson = object(person);
/*
注意, 在ES5中新增了Object.create()方法规范了原型式继承, 该方法接受两个参数, 一个是用作新对象原型的对象, 一个为新对象定义的额外方法
var anotherPerson = Object.create(person);
*/
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");

alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie" 子类中对对象的修改会影响基类的对象的调用.

 

5. 寄生式组合式继承

主要用于解决组合继承中调用两次构造函数的问题, 该方法通过借用构造函数来继承属性, 通过原型链的混成形式来继承方法.

其高效率体现在它只调用了一次SuperType的构造函数, 避免了在SubType的prototype上创建不必要的, 多余的属性, 目前最理想的继承方式.

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

function inheritPrototype(subType, superType){
    var prototype = object(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(){
    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

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。