前提: 组合指的是什么?就是这两部分的组合:构造函数属性的继承和建立子类和父类原型的链接。
借用构造函数继承
最简单的方法,使用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构造函数,并不会创建不必要的、多余的属性。与此同时,原型链还能保持不变;开发人员普遍认为寄生组合式继承是引用类型最理想的继承方式.