基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法,即让原型对象等于另一个类型的实例(即要继承的对象的实例)
原型链式继承
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
}
function SubType() {
this.subpropertype = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
return this.subpropertype;
}
var ins = new SubType();
console.log(ins.subpropertype);//false
console.log(ins.getSuperValue());//true
注意:
1.给原型添加方法的代码一定要放在替换原型的语句之后
2.在创建子类型的实例时,不能向超类型的构造函数中传递参数
基本思想:在子类型构造函数的内部调用超类型构造函数,通过使用apply()和call()方法可以在将来新创建的对象上执行构造函数
构造函数式继承
function SuperType(){
this.color=['1','2','3','4'];
}
function SubType(){
SuperType.call(this);
}
var ins1=new SubType();
ins1.color.pop()
console.log(ins1.color);//[1,2,3]
var ins2=new SubType()
ins2.color.push('5');
console.log(ins2.color);//[1,2,3,4,5]
优点:可以在子类型构造函数中向超类型构造函数传递参数
缺点:在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式
**
**
基本思想:将原型链和借用构造函数技术组合到一起。使用原型链实现对原型属性和方法的继承,用借用构造函数模式实现对实例属性的继承。这样既通过在原型上定义方法实现了函数复用,又能保证每个实例都有自己的属性
组合继承
function SuperType(name){
this.name=name;
this.color=[1,2,3,4];
}
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;
//构造函数的原型的constructor属性的值应该指向构造函数本身。
SubType.prototype.sayAge=function(){
return this.age
}
var ins1=new SubType('lisi',20);
ins1.color.pop();
console.log(ins1.color);//[1,2,3]
console.log(ins1.sayName());//lisi
console.log(ins1.sayAge());//20
var ins2=new SubType('wanhwu',22)
ins2.color.push(5);
console.log(ins2.color);//[1,2,3,4,5]
console.log(ins2.sayName());//wangwu
console.log(ins2.sayAge());//22
基本思想:不用严格意义上的构造函数,借助原型可以根据已有的对象创建新对象的特性,还不必因此创建自定义类型,因此最初有如下函数:
function object(o){
function F(){}
F.prototype = o;
return new F();
}
var person = {
name:'Annika',
friendes:['Alice','Joyce']
};
var anotherPerson = object(person);
anotherPerson.name = 'Greg';
anotherPerson.friendes.push('Rob');
var yetAnotherPerson = object(person);
yetAnotherPerson.name = 'Linda';
yetAnotherPerson.friendes.push('Sophia');
console.log(person.friends); //['Alice','Joyce','Rob','Sophia']
ES5通过新增的Object.create()方法规范化了原型式继承。
这个方法接受了两个参数,一个用作新对象原型的对象,
一个为新对象定义额外属性的对象(可选的)
Object.create() 方法会使用指定的原型对象及其属性去创建一个新的对象。
var person = {
name:'Annika',
friends:['Alice','Joyce']
};
var anotherPerson = Object.create(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Rob');
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = 'Linda';
yetAnotherPerson.friends.push('Sophia');
yetAnotherPerson.age=20;
console.log(person.friends,yetAnotherPerson.age); //['Alice','Joyce','Rob','Sophia'],20]
Object.create()方法的第二个参数与Object.difineProperties()方法的第二个参数格式相同:
每个属性都是通过自己的描述符定义的,以这种方式指定的任何属性都会覆盖原型对象上的同名属性,
例如:
var anotherPerson=Object.create(person,{
name:{
value:'tom'
}
});
基本思想:寄生式继承是与原型式继承紧密相关的一种思路,它创造一个仅用于封装继承过程的函数,在函数内部以某种方式增强对象,最后再返回对象。
function createAnother(original){
var clone=object(original);
clone.say=function(){
console.log('hi,sb');
}
return clone;
}
其中规范模式时使用的object()函数不是必需的,
任何能够返回新对象的函数都适用于此模式
person={
name:'lisi',
age:20
}
var anotherPerson=createAnother(person);
person.say();
基本思想:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法,不必为了指定子类型的原型而调用超类型的构造函数,只需要超类型的一个副本。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型
function SuperType(name){
this.name=name;
this.colors=['red','blue','green'];
}
SuperType.prototype.getSuperValue=function(){
return this.name;
}
function SubType(name,age){
SuperType.call(this,name);
this.age=age;
}
function inherit(subType,superType){
var prototype=Object.create(superType.prototype);
prototype.constructor=subType;
subType.prototype=prototype;
}
inherit(SubType,SuperType);
//最好置于继承方法的最前边
SubType.prototype.getSubValue=function(){
return this.age;
}
var instance=new SubType("John",20);
console.log(instance.getSubValue()); //输出20
console.log(instance.getSuperValue()); //输出"John",成功调用在父类原型定义的方法