js实现构造函数继承的extend方法

现在有两个构造函数 SuperChild

如何实现Child 继承 自Super

function Super() {
    this.age = 12
}
Super.prototype.sayHello = () => { }

function Child() {
    this.color = 'red'
}
Child.prototype.getColor = () => { }

首先分别 new 一下两个函数
在这里插入图片描述

控制台打印出两个实例,他们分别都有自己的实例属性以及原型方法

先声明一下,下文中:

  • Child 指的是Child构造函数
  • Child对象 指的是用Child构造函数生成的实例
  • Super 指的是Super构造函数
  • Super对象 指的是Super构造函数生成的实例

观察Child对象,他的原型[[prototype]] 是一个Object对象,若Child继承了Super以后,Child对象的原型[[prototype]]将换成Super对象

如何做到上面的效果?

要替换Child对象的原型[[prototype]],就需要替换Child构造函数的原型prototype
举个栗子:

Child.prototype = {
    info:'我替换了Child的prototype'
}

上面一行代码就把Childprototype替换了,又叫原型重写,继续:

Child.prototype = new Super()

这一句代码的意思就是把Childprototype重写成Super对象,到这里,似乎实现了最简单的继承,运行试试
完整代码:

function Super() {
    this.age = 12
}
Super.prototype.sayHello = () => { }

function Child() {
    this.color = 'red'
}
Child.prototype.getColor = () => { }
Child.prototype = new Super()
console.log(new Child());

在这里插入图片描述
我们发现Child对象的原型确实变成Super,但是存在一个问题,Child原型上定义的getColor 方法丢失了,constructor好像也丢失了,而且Child原型上还多了age属性,这是我们不希望看到的,于是:

function Super() {
    this.age = 12
}
Super.prototype.sayHello = () => { }

function Child() {
    this.color = 'red'
}
Child.prototype.getColor = () => { }

const prototype = Object.create(Super.prototype)
prototype.constructor= Child
prototype.getColor = Child.prototype.getColor
Child.prototype = prototype
console.log(new Child());

在这里插入图片描述
这里我们创建了一个空对象prototype ,并且复制Child.prototype上的getColor到空对象身上,然后重写Child原型
打印的结果很接近完美了,这样做还有个问题,如果Child.prototype上面原本有多个方法呢?得想个办法完整复制原来的方法

function Super() {
    this.age = 12
}
Super.prototype.sayHello = () => { }

function Child() {
    this.color = 'red'
}
Child.prototype.getColor = () => { }
Child.prototype.getName = () => { }

const prototype = Object.create(Super.prototype)
prototype.constructor= Child
for (const [key, value] of Object.entries(Child.prototype)) {
    prototype[key] = value // 复制Child原型原来的属性以及方法
}
Child.prototype = prototype
console.log(new Child());

在这里插入图片描述
到这里,就能完整复制Child原型原来的属性以及方法了

把这几个步骤封装成函数

/**
 * 继承
 * @param {Function} Child 子类
 * @param {Function} Super 超类(父类)
 */
function extend(Child, Super) {
    const sp = Super.prototype// 父类原型
    const sub = Child.prototype // 子类原型
    const prototype = Object.create(sp)// new出来一个纯净的对象,并且__proto__指向父类原型
    for (const [key, value] of Object.entries(sub)) {
        prototype[key] = value // 复制子类原型原来的属性以及方法
    }
    // 显式声明构造器(不可枚举)
    Object.defineProperty(prototype, 'constructor', {
        enumerable: false,
        configurable: true,
        value: Child
    })
    Child.prototype = prototype// 重写原型
}

Object.defineProperty() 表示:定义对象自身上的属性,具体用法可以自行百度

现在可以愉快的使用继承了,测试:

function Super() {
    this.age = 12
}
Super.prototype.sayHello = () => { }

function Child() {
    this.color = 'red'
}
Child.prototype.getColor = () => { }

extend(Child, Super)// 执行继承
console.log(new Child())

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值