ECMAScript中只支持实现继承,而实现继承主要是依靠原型链来实现的。
1.原型链
原型链的主要思想是利用原型,让一个引用类型的属性和方法继承另一个引用类型的属性和方法。
Q:构造函数、原型和实例之前的关系
every构造函数都有一个原型对象;
原型对象里还都有一个constructor属性指向拥有这个属性的原型对象;
every实例都包含一个指向原型对象的内部指针。
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subproperty = false;
}
//inherit from SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); //true
alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true
alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true
用上面的instanceof来确定原型和实例的关系;或者用下面的isPrototypeOf()方法来确定。
2.借用构造函数
原型链的继承固然不错,但是如果包含引用类型的原型就会出现问题;再者就是在创建子类型的实例时,不能向超类型的构造函数中传递参数。由此有了这个借用构造函数。通过在子类型的构造函数内调用超类型的构造函数(通过call或者apply来实现的)
function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
//inherit from SuperType
SuperType.call(this);
}
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"
传递参数例子
function SuperType(name){
this.name = name;
}
function SubType(){
//inherit from SuperType passing in an argument
SuperType.call(this, "Nicholas");
//instance property
this.age = 29;
}
var instance = new SubType();
alert(instance.name); //"Nicholas";
alert(instance.age); //29
通过使用call或者apply的方法,完成在特定环境下调用函数方法,这里面实际上是在新创建的SubType实例的环境下调用了SuperType构造函数。
网友评论