继承
总结: 1.引用类型共享(出处:原型链继承;解决:构造函数定义属性 )
2. 无法向超类型构造函数传递参数 (出处:原型链继承 解决:在子类型构造函数中调用超类型构造函数,并改 变this指向)
3.方法复用 (出处:抛弃原型链继承; 解决:启用原型链继承)
4.子实例.constructor指向超类型构造函数 (出处:原型链继承 ; 解决:手工修改)
5.实例与原型属性重复 (出处:组合继承调用两次构造函数 ;解决:寄生组合继承,子类型的原型直接指向超类 型的原型)
6.isPrototypeOf()识别问题 (出处:抛弃原型链继承; 解决:组合继承)
1.原型链
function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
}
//继承了SuperType
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green,black"
缺点:1.引用类型共享问题
2.在创建子类型的实例时,不能向超类型的构造函数中传递参数,由于子实例的原型都为超实例,超实例的属性 会共享
3.子实例.constructor指向Supertype
优点:可以实现继承
2.借助构造函数(经典继承)
function SuperType(name){
this.colors = ["red", "blue", "green"];this.name = name;
}
function SubType(name){
//继承了SuperType ,同时还传递了参数SuperType.call(this, name);//实例属性this.age = 29;
}
优点:子类型构造函数中可以向超类型构造函数传递参数,子实例不会共享属性
缺点:方法都在构造函数中定义,因此函数复用就无从谈起了,isPrototypeOf()识别问题
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指针,并执行SuperType函数this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
优点:解决经典继承的缺点,而且,instanceof 和isPrototypeOf()也能够用于识别基于组合继承创建的对象
缺点:调用了两次父构造函数,子实例和子实例的原型有两套相同的属性,占用内存
4.原型式模式
function object(o){
function F(){}F.prototype = o;return new F();
}
var person = {
name: "Nicholas",friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = object(person);
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
原型式继承改进
var person = {
name: "Nicholas",friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = Object.create(person, {
name: {value: "Greg"}
});
alert(anotherPerson.name); //"Greg"
特点:从本质上讲,object()或者Object.create()对传入其中的对象执行了一次浅复制,
优点:简单,不用设计构造函数,需要的属性再设定
缺点:原型中如果包含引用类型值的属性始终都会共享相应的值,原型模式一样也具有相同问题(基本类型的属性可以在实例中创建同名 属性屏蔽)。
5.寄生式继承(原型模式继承的加强)
function createAnother(original){
var clone = object(original); // 通过调用函数创建一个新对象
clone.sayHi = function(){ // 以某种方式来增强这个对象
alert("hi");
};
return clone; //返回这个对象
}
优点:同上。方法在不扩展原生对象原型的情况下自定义一个扩展型的对象,增加对象的方法。
缺点:同上。使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率,这一点与构造函数模式类似
6.寄生组合式继承(推荐)
function inheritPrototype(subType, superType){//替代SubType.prototype = new SuperType();的继承功能,又避免了调用父构造函数
var prototype = object(superType.prototype);subType.prototype = prototype;prototype.constructor = subType;
}
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);
};
优点;解决了组合继承的缺点

浙公网安备 33010602011771号