JavaScript—八大继承

539 阅读2分钟

原型链式继承

继承的本质就是复制,即重写原型对象,代之以一个新类型的实例

function SuperType(){
    this.name = "Nancy";
    this.colors = ["red","blue","green"];
}
SuperTyoe.prototype.getSuperValue = function(){
    console.log(this.name);
}
function SubType(age){
    this.age = age;
}
SubType.prototype = new SuperType();
//此步与上步顺序不可变
SubType.prototype.getSubValue = function(){
    console.log(this.age);
}

var sub1 = new SubType(23);
sub1.colors.push("black");      //red、blue、green、black

var sub2 = new SubType(22);
console.og(sub2.colors);                    //red、blue、green、black

缺点:多个实例对引用类型的操作会篡改

借用构造函数继承

借用父类的构造函数来增强子类的实例,等于上复制父类的实例给子类(不使用原型)

function SuperType(){
    this.colors = ["red","blue","green"];
}
function SubType(){
    SuperType.call(this);
}

var sub1 = new SubType();
sub1.colors.push("black");      //["red","blue","green","black"]

var sub2 = new SubType();
sub2.colors;                    //["red","blue","green"]

只能继承父类实例的属性和方法,不能继承原型中的属性和方法; 无法实现复用,每个子类实例都有父类实例函数的副本,影响性能

组合继承

用原型链实现对父类原型属性/方法的继承,用构造函数技术实现对父类实例属性/方法的继承

function SuperType(name){
    this.name = name;
    this.color = ['red','blue','green'];
}
SuperType.prototype.sayName = function(){
    return this.name;
}
function SubType(name,age){
    SuperType.call(this,name);
    this.age = age;
}
//构建原型链
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    return this.age;
}

var sub1 = new SubType("Tony",11);
sub1.colors.push("black");          //'red','blue','green','black'

var sub2 = new SubType("Mary",10);
console.log(sub2.colors);           //'red','blue','green'

缺点:在实例原型中存在两份相同的属性和方法

原型式继承

利用一个空对象作为中介,将父属性直接赋值给空对象构造函数的原型

function object(obj){
    function F(){};
    F.prototype = obj;          //对传入的对象进行一次浅复制
    return new F();
}

var parent = {
    name:"Mary",
    colors:['red','blue','green']
};
var obj1 = object(parent);
obj1.name = "Mary1";
obj1.colors.push("black");

console.log(parent.colors);     //'red','blue','green','black'

缺点:
原型链继承的多个实例的引用类型属性指向相同,存在篡改;
不能传递参数

寄生式继承

在原型式的继承的基础上,增强对象,返回构造函数

function createAnother(original){
    var clone = object(original);
    clone.sayHi = function(temp){       //以某种方式来增强对象
        console.log(temp);
    }
    return clone;
}
var cre1 = createAnother(parent);

缺点:
原型链继承的多个实例的引用类型属性的指向一样,存在篡改可能性;
不能传参

寄生组合式继承

借用构造函数式继承和寄生式继承实现

function inheritProperty(subType,superType){
    var property = Object.create(superType.prototype);
    property.constructor = subType;     //增强对象
    subType.prototype = prototype;
}
function SuperType(name){
    this.name = name;
    this.color = ['red','blue','green'];
}
SuperType.prototype.sayName = function(){
    return this.name;
}
//借用构造函数来增强子类实例属性(支持传参和避免篡改)
function SubType(name,age){
    SuperType.call(this,name);
    this.age = age;
}
//将父类原型指向子类原型
inherit(SubType,SuperType);
//新增子类属性
SubType.prototype.sayAge = function(){
    return this.age;
}

var inh1 = new SubType("Tony",11);

此方法的高效性在于,只调用SuperType构造函数一次,避免了SubType.prototype中出现重复的属性和方法,同时原型链不变,instanceof和isPropertyOf()还可以正常使用。这是目前最成熟的方法,也是现在库实现的方法

混入方式继承多个对象

es6继承extends