JS继承有四种方式,分别是组合继承、原型式继承、寄生式继承、寄生组合式继承。其中最常用的是组合继承。
1.组合继承:使用原型链继承共享的属性和方法,通过构造函数继承实例属性
function Animal(name){
this.name = name;
}
Animal.prototype.sayName = function(){
alert(this.name);
}
function Dog(name,age){
Animal.call(this,name); //借用构造函数 继承属性 // 第二次调用Animal()
this.age = age;
}
//原型链 继承方法
Dog.prototype = new Animal(); //第一次调用Animal()
Dog.prototype.constructor = Dog;
Dog.prototype.sayAge = function(){
alert(this.age);
}
组合继承
原理:将原型链和借用构造函数的技术结合在一起。使用原型链实现对原型属性和方法的继承,同时借用构造函数来实现对实例属性的继承。
优点:避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为js中最常用的继承模式,而且,instanceof和isPrototypeOf也能够识别基于组合继承创建的对象。
缺点:无论在什么情况下,都会调用两次超类型构造函数(父类构造函数):一次是在创建子类型原型的时候,一次是在子类型构造函数内部。
2.原型式继承:执行给定对象的浅复制,复制得到的副本可以进一步改造。
旧版:
function object(o){ // 本质是对参数o执行一次浅复制
function F(){} // object函数内部先创建了一个临时性的构造函数F
F.prototype = o; // 然后将传入的参数o作为这个临时构造函数的原型
return new F(); // 最后返回这个临时类型的一个新实例
}
var person = {
name:"Jack",
friends:["Van","Sherlly"]
};
var anotherPerson = object(person); //浅复制给定的对象person
anotherPerson.name = "Mark"; //原型对象person的同名属性会被覆盖
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Lin";
yetAnotherPerson.friends.push("Zee");
alert(person.friends); //"Van","Sherlly","Rob","Zee"
新版:(ES5新增了Object.create()方法,规范化了原型式继承,这个方法接收两个参数,一个用作新对象原型的对象和一个为新对象定义额外属性的对象,在传入一个参数的情况下,Object.create()与object()方法的行为相同)
var person = {
name:"Jack",
friends:["Van","Sherlly"]
};
var anotherPerson = Object.create(person); //浅复制给定的对象person
anotherPerson.name = "Mark"; //原型对象person的同名属性会被覆盖
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Lin";
yetAnotherPerson.friends.push("Zee");
alert(person.friends); //"Van","Sherlly","Rob","Zee"
原型式继承
原理:
优点:
缺点:
3.寄生式继承:基于给定对象或信息创建一个对象,然后增强对象并返回。
var clone = object(original); //通过调用object函数创建一个新对象
clone.sayHi = function(){ //增强对象
alert("Hi!");
}
return clone; //返回对象
}
寄生式继承
原理:
优点:
缺点:
4.寄生组合式继承:集寄生式继承和组合继承的优点于一身,是实现类型继承的最有效的方法。
function intheritPrototype(child,parents){
var prototype = object(parents.prototype); //创建对象
prototype.constructor = child; //增强对象
child.prototype = prototype; //指定对象
}
function Animal(name){
this.name = name;
}
Animal.prototype.sayName = function(){
alert(this.name);
}
function Dog(name,age){
Animal.call(this,name);
this.age = age;
}
intheritPrototype(Dog,Animal);
Dog.prototype.sayAge = function(){
alert(this.age);
}
寄生组合式继承
原理:
优点:与组合继承相比,只调用了一次父类构造函数,并且因此避免了在子类原型上面创建不必要的多余的属性,同时,原型链环还能保持不变,因此能够正常地使用instanceof和isPrototypeOf。普遍认为寄生组合式继承是引用类型最理想的继承范式。
缺点: