2

前提: 组合指的是什么?就是这两部分的组合:构造函数属性的继承和建立子类和父类原型的链接。

借用构造函数继承

最简单的方法,使用call或apply方法,将父对象的构造函数绑定在子对象上

function Super(name){
    this.name=name;
    this.friends = ['小红','小强'];
}
Super.prototype.sayName = function(){
    alert(this.name)
};
function Sub(name){
    Super.apply(this,arguments);
}

var instance1 = new Sub('小明');
var instance2 = new Sub('小明');
instance1.friends.push('张三');
console.log(instance1.friends);//["小红", "小强", "张三"]
console.log(instance2.friends);//["小红", "小强"]

缺点: 没办法继承超类中的原型属性和方法


原型链继承

        function Super(){
            this.name="小明";
        }
        Super.prototype.sayName = function(){
            alert(this.name)
        };
        function Sub(){}
        
        Sub.prototype = new Super();
        
        Sub.prototype.constructor = Sub;  
        //此句的作用是为了不让继承链的紊乱,因为任何一个prototype对象都有一个constructor属性,指向它的构造函数,
        //并且每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性,
        //所以new Animal()的constructor指向Super,导致Sub.prototype.constructor改而指向了Super 为了不导致紊乱 所以要手动指回
        
        var instance = new Sub();
        instance.sayName();//小明

缺点:
1.当父类中包含引用类型属性值时,其中一个子类的多个实例中,只要其中一个实例引用属性只发生修改一个修改,其他实例的引用类型属性值也会立即发生改变
2.原因是父类的属性变成子类的原型属性


组合式继承
(原型继承+借用构造函数继承)

    
        function Super(){
        this.name="小明";
            this.friends = ['小红','小强'];
        }
        Super.prototype.sayName = function(){
            alert(this.name)
        };
        function Sub(){
            Super.call(this);
        }
        
        Sub.prototype = new Super();
        var instance1 = new Sub();
        var instance2 = new Sub();
        instance1.friends.push('张三');
        console.log(instance1.friends);//["小红", "小强", "张三"]
        console.log(instance2.friends);//["小红", "小强"]
        instance1.sayName();//小明
        instance2.sayName();//小明

缺点:
1.两次调用父构造函数 并且子类的自由属性和原型链上的属性会重复覆盖 (打印instance1对象 instance1.prototype和instance1都有一个name属性)
2.同原型链继承的第一个缺点


寄生组合式继承
寄生组合式继承 两步:

1.在子类中调用父类的构造函数:
  Super.apply(this,arguments)
2.建立子类和父类原型的链接 
  最简单的方法就是用Object.create()方法对父类的原型进行浅复制,赋给子类原型:
  Sub.prototype=Object.create(Super.prototype);   //相比之前的原型链继承方法:SubType.prototype=new SuperType();这里没有创建构造函数;

    //寄生组合式继承函数
        function inheritPrototype(sub,super){
            var prototype=Object.create(super.prototype) 
            prototype.constructor = sub; //增强对象
            sub.prototype = prototype; //最后指定对象  
        }
   
    //最终的实现方法
        function Super(name){
            this.name=name;
        }
        Super.prototype.sayName=function(){console.log(this.name)}
        
        function Sub(name,age){
            Super.call(this,name);
            this.age=age;
        }
        inheritPrototype(SubType,SuperType); //实现继承
        
        //其实,说白了寄生组合式继承就是一个借用构造函数 + 相当于浅拷贝父类的原型对象

这种方式的高效率体现它只调用了一次Parent构造函数,并不会创建不必要的、多余的属性。与此同时,原型链还能保持不变;开发人员普遍认为寄生组合式继承是引用类型最理想的继承方式.


2000exists
5 声望2 粉丝