JS实现继承的多种方式(一)

注:部分名词和示例代码摘自高程及犀牛书,即站在巨人的肩膀上?


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继承实现的多种方式(二)

发布了18 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41597258/article/details/84950216