javascript支持实现继承。而继承是通过原型链实现的。继承的本质就是重写原型对象,代之以一个新类型的实例。
1.原型链
原型链,简而言之,就是原型与实例的链条。通过让原型对象等于另一个类型的实例实现的,这样这个引用类型就 继承了另一个引用类型的属性和方法(包括实例属性和原型对象的属性和方法)。
所有的引用类型都默认继承了object。这个继承就是通过原型链实现的。
每个对象都有一个_proto_属性,指向创建该对象的函数的prototype。
所有的函数的默认原型都是object的实例,因此默认原型都有一个内部指针[[prototype]](firefox、sarari、chrome在每个对象上支持_proto_属性),指向Object.prototype。(所有自定义函数的prototype原型对象,本质上和var obj={}一样,默认都是由object创建的,所以它的prototype属性指向object.prototype。)
但是object.prototype也有一个_proto_属性,该属性指向null。
注意:使用原型链实现继承时,不能使用对象字面量创建原型方法,因为会重写原型链。
问题:
1.引用类型的问题。超类型的实例属性会变成子类型的原型属性。所以子类型的原型属性中会有超类型的引用类型值的实例属性。而该属性会被会被所有实例共享。
2.没有办法再不影响所有的对象实例的情况下,给超类型的构造函数传递参数。(子类型的原型对象包含超类型的实例属性,所以改变超类型的构造函数,会影响子类型的原型对象);
2.借用构造函数(解决了问题1)
基本思想:在子类型的构造函数内部调用超类型构造函数
function SuperType(){
this.colors=["blue","red","green"];
}
function SubType(name,age){
SuperType.call(this,name);
}
var person1=new subType("tian",13);
var person2=new subType("chen",14);
此时,colors是实例属性。person1和person2都有各自的colors属性,不会相互影响。
3.组合继承
组合继承:原型链和借用构造函数。是javascript中最常用的继承方式。
基本思想:使用原型链实现对原型属性和方法的继承,使用借用构造函数来实现对实例属性的继承。
function SuperType(name){
this.name=name;
this.colors=["blue","red","green"];
}
SuperType.prototype.sayName=function(){
alert(this.name);
}
function SubType(name,age){
SuperType.call(this,name);
this.age=age;
}
subType.prototype=new SuperType();
Subtype.protptype.constructor=Subtype;
Subtype.prototype.sayAge=function(){
alert(this.age);
}
var person1=new subType("tian",13);
var person2=new subType("chen",14);
4.原型式继承
相当于对o对象执行了一次浅复制。
function object(o){
function F(){}
F.prototype=o;
return new F();
}
ECMAScript5新增方法Object.create()方法规范了原型继承。接受两个参数:
1.用作新对象原型的对象
2.为新对象定义额外属性的对象。
5.寄生组合式构造函数(解决了问题1,2)(最理想的继承方式)
function inheritPrototype(subType,superType){
var prototype=object(superType.prototype); //创建了对象
protptype.constructor=subType;
subType.prototype=prototype;
}
function SuperType(name){
this.name=name;
this.colors=["blue","red","green"];
}
SuperType.prototype.sayName=function(){
alert(this.name);
}
function SubType(name,age){
SuperType.call(this,name);
this.age=age;
}
inheirtPrototype(subtype,superType);
Subtype.prototype.sayAge=function(){
alert(this.age);
}
var person1=new subType("tian",13);
此时,SubType的原型对象中不再含所有name、colors属性。