注:部分名词和示例代码摘自高程及犀牛书,即站在巨人的肩膀上?
1. 原型链继承
将父类的属性及原型方法初始化给实例原型,即让一个引用类型值继承另一个引用类型的属性和方法
function SuperType() {
this.property = false
}
SuperType.prototype.getSuperValue = function () {
console.log(this.property)
}
function SubType() {
this.subProperty = true
}
SubType.prototype = new SuperType()
// 重写父类的方法,在原型链赋值后
// SubType.prototype.getSuperValue = function () {
// console.log("reset from super")
// }
SubType.prototype.getSubValue = function () {
this.getSuperValue() // 调用父类的方法
console.log(this.subProperty) // 获取当前实例的值
}
var instance = new SubType()
instance.getSubValue() // -> false true
重写原型对象,代之以新类型的实例,相关信息如下
// 输出当前实例的详细信息
console.dir(instance)
// 确定当前原型和实例的从属关系
console.log(instance.constructor) // -> SuperType
console.log(instance instanceof Object) // -> true
console.log(instance instanceof SuperType) // -> true
console.log(instance instanceof SubType) // -> true
缺陷:未对父类的值进行解引, 即原型属性被实例属性共享, 构造器从属关系不明确
测试代码
function SuperType() {
this.colors = ["red","yellow","blue"]
}
function SubType() {}
SubType.prototype = new SuperType()
SubType.prototype.constructor = SubType // 指定当前实例的构造函数
var instance = new SubType()
instance.colors.push("black")
var instance2 = new SubType()
console.log(instance.colors) // -> ["red","yellow","blue","black"]
console.log(instance2.colors) // -> ["red","yellow","blue","black"]
2. 经典继承
在子类构造函数中调父类构造函数
function SuperType() {
this.colors = ["red","yellow","blue"]
this.getLast = function(){ // 超类型原型方法
return this.colors[this.colors.length - 1]
}
}
function SubType() {
// 借调超类型的构造函数
SuperType.call(this) // this随当前执行环境绑定,为每个实例创建唯一标识符
}
var instance = new SubType()
instance.colors.push("black")
// 重写父类的方法
// instance.getLast = function () {
// return "reset from super"
// }
var instance2 = new SubType()
console.dir(instance)
console.log(instance.getLast()) // -> black
console.log(instance2.getLast()) // -> blue
在SubType对象上执行借调(个人理解)SuperType中的对象初始化代码,近似于一个共用的函数巧妙的利用了this的动态性
优点:取消了实例属性共享(通过创造副本),优化构成器从属关系
缺陷:无法抽离出共用的一些方法(代码复用),需为每个实例重赋值一次
3. 组合继承(伪经典继承)
即使用原型链实现对原型方法的继承,借用构造函数实现对实例属性的继承
function SuperType(name) {
this.name = name
this.colors = ["red","yellow","blue"]
}
SuperType.prototype.getSuperValue = function () {
console.log(this.name)
}
function SubType(name) {
// 继承属性
SuperType.call(this, name)
this.subProperty = true
}
//继承方法
SubType.prototype = new SuperType()
SubType.prototype.constructor = SubType // 指定当前实例的构造函数
SubType.prototype.getSubValue = function(){
console.log(this.subProperty)
}
var instance = new SubType("yun")
var instance2 = new SubType("touda")
instance.colors.push("black")
console.dir(instance)
instance.getSuperValue() // -> yun
instance.getSubValue() // -> true
console.log(instance.colors) // -> ["red","yellow","blue","black"]
console.log(instance2.colors) // -> ["red","yellow","blue"]
分别继承,对于父类的属性用经典模式,方法则采用原型链模式 ,并完善构造器从属关系
优点:融合了经典模式和原型链模式,形成互补
友情链接: JS继承实现的多种方式(二)