js 怎么使一个absolute覆盖在父类上面_javascript 继承的一个小问题

70d26aef5251d7019f63d679c2d8d0fb.png

首先,js 继承是怎么回事?

js 的继承基础是原型链, 在这之上, 在 es6 里加入了 class , 也实现了 extends, 也有了 super 关键字

大概语法是这么回事

class Sup {
    name = 'sup-class'
    init() {
        console.log(this.name)
    }
}
class Sub extends Sup {
    init() {
        super.init()
    }
}

我最近遇到一个问题:

class Sup {
    constructor() {
        this.init()
    }
    name = 'sub-class'
    init() {
        console.log(this.name)
    }
}

class Sub extends Sup {
    name2 = 'sub-class'
    init() {
        super.init()
        console.log(this.name2)
    }
}

乍一看,貌似也没什么问题 ?

但是这个玩意儿,执行 new Sub() 运行出来的 结果, 第二处打印的是 undefined

9d7182d7a46d799242b287a9431335a3.png
test

我一开始遇到这个坑的时候, 还没反应过来, 为啥这里是 undefined ?

由于我一开始写的是 typescript, 所以习惯了不写构造函数, 就更加难以察觉这个问题

终于我去看了 一眼编译后的结果

这东西编出来的结果是这样的 -- 选择 tsc 的编译目标为 es2018 的话 -- 上面这个代码, 本质上跟下面这个是一致的

class Sup(){
    constructor(){
        this.name = 'sub-class'
        this.init()
    }
    init(){
        console.log(this.name)
    }
}
class Sub extends Sup{
    constructor(){
        super()
        this.name2 = 'sub-class'
    }
    init(){
        super.init()
        console.log(this.name2)
    }
}

简单看过去,貌似还是没有什么问题

问题到底在哪里?

在于 js 的继承机制, js 的继承, 本质上是处理原型链, 对于对象本身的处理, 是先构造一个子类对象, 然后用父类的构造喊出来处理子类对象

也就是说, 在创建 Sub 的时候, 虽然去调用了父类的构造函数, 执行了 super(), 但是并没有针对父类构造对象出来, 那么在父类的构造函数里的 this 关键字, 指向谁呢?

答案是 : 子类的实例

那么现在这个问题就好理解了: 由于在创建 Sub 实例的时候, 父类的构造函数执行的时候, 内部的 this 其实是只想 Sub 实例的, 所以这里调用的 this.init 其实是 Sub.prototype.init , 然后子类又去调用了父类的 init 方法, 才讲父类的内容打印出来

那么为什么打印自己的 name2 的时候, 是undefined?

看看上面的代码: super(); this.name2 = 'sub-class'

所以这里的执行顺序为

Sub.construct
    -> Sup.construct
        -> this.name = ''
        -> Sub.init
                -> Sup.init
                    -> console.log(this.name)
                -> console.log(this.name2)
    -> this.name2 = ''

这样就清晰了吧, 为什么? 因为执行的时候, name2 还没初始化呢

如果不理解这些比较虚的东西, 改成原型链来看看:

function Sup(){
    this.name = 'sub-class'
    this.init()
}
Sup.prototype.init = function (){
    console.log(this.name)
}

/**这里的继承, 就不写那种很通用的继承函数了*/

function Sub(){
    Sup.call(this)
    this.name2 = 'sub-class'
}
Sub.prototype.init = function (){
    //这里要实现一个 super 的效果
    Sub.prototype.__proto__.init.call(this)
    console.log(this.name2)
}

Sub.prototype.__proto__ = Object.create(Sup.prototype)

以上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值