JavaScript中的继承,ES6中class和extends的原理

        我在上一篇博客中介绍了JavaScript中new操作的原理,那么就接下来就来探索下,ES6中引进的class和extends的原理吧。

class的原理

        首先,先来看看class声明的用法。

class person{
    //等同于原生继承中的person构造方法
    constructor(name,age){
        //person='str' 内部是不能类名的
        this.name=name
        this.age=age
    }
    //静态方法,等同于原生继承中的person.getAge
    static getAge(){
        return this.age
    }
    //实例方法,等同于原生继承中的person.prototype.setName
    getName(){
        return this.name
    }
}
const p=new person('Tom',20)
p.getAge() //20
p.getName() //'Tom'
console.log(p instanceof person) //true
console.log(typeof person) //function
console.log(person.getAge) //getAge(){}
console.log(p.getName === person.prototype.getName) //true
person='str' //类声明结束后是可以作为变量修改的

        ES6的class关键字和其他面向对象语言的使用方法类似,通过class来定义类,通过constructor方法名来定义构造函数,但有意思的是,ES6中的class声明仅仅只是自定义类型的语法糖,从上面代码我们可以看出,typeof person 打印出来的是一个‘function’,所以class声明的类实际上是创建了一个具有构造函数方法行为的函数。

        我们可以尝试来写一下class的原理,上面的类声明等价与如下代码。

//类声明时不能够变量提升的,但可以被同名声明替代,与let声明类似
let person = (function () {
    //class声明中所有代码都是运行在严格模式下的
    "use strict"
    //class关键字内部无法将类名作为变量修改,与const类似
    const person = function (name, age) {
        //确保通过new关键字调用
        if (typeof new.target === "undefined")
            throw new Error("必须用new调用构造函数")
        this.name = name
        this.age = age
    }
    //class声明中的方法都是不可枚举的,用Object.defineProperty实现
    Object.defineProperty(person,"getAge",{
        value:function(){
            return this.age
        },
        enumerable:false,
        writable:true,
        configurable:true
    })
    Object.defineProperty(person.prototype,"getName",{
        value:function(){
            return this.name
        },
        enumerable:false,
        writable:true,
        configurable:true
    })
    
    return person
})

        class声明其实做了很多事情,就像上面代码演示的那样,但其实我觉得class声明和原生实现类的最主要区别还是使类声明符合大众的习惯,使代码简介明了。

extends继承的原理

        接下来我们来探究下class的继承extends的原理吧,来看看在ES6之前我们是如何实现类继承的。

function person(name) {
    this.name = name
}
person.prototype.getName = function () {
    return this.name
}
function stu(name, age) {
    person.call(this, name) //调用父类的构造方法,使this执行子类,super的原理
    this.age = age
}
//创建一个自父类原型的新对象重写子类的原型
stu.prototype = Object.create(person.prototype, {
    constructor: {
        value: stu,
        enumerable: true,
        writable: true,
        configurable: true
    }
})

        其实extends的原理也很简单,就是利用Object.create()创建一个新对象,这个对象原型指向父类原型,其中有constructor指向子类构造函数,利用原型链的知识就可以实现extends继承的基本功能了,这便是extends的基本原理。

        最后,我们再来看看class继承的基本使用吧。

class person {
    constructor(name) {
        this.name = name
    }
    getName() {
        return this.name
    }
}
class stu extends person {
    constructor(name, age) {
        super(name) //等价于person.call(this,name)
        this.age = age
    }
    getAge() {
        return this.age
    }
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值