JS类的继承和实现原理详解

一:前言

各位小伙伴在日常开发中,相信一定遇到过Class这种写法。这代表在JS中创建了一个类,并且可以通过这个类去 new 出一个新的对象。其实在JS中,这个类和java中的类是没有区别的,同样具有属性,方法,构造器等。接下来请跟随我的步伐,一起来看一下其包含的内容吧~

二:Class介绍

1、基础语法

通过下面的代码,我们可以看到,首先定义了一个person类,其中有两个公有属性,分别是有默认值的age,和没有默认值的name。再往下是一个构造器,这个构造器要求传递一个参数,所以当我们调用这个类去实例化对象的时候,必须传递一个参数,这个参数就是name的值。而后有两个公有方法,分别返回了两个不同的语句。具体运行效果可以参考下方的图。

javascript 复制代码
    <script>
        class person{
            // 这是两个公有属性
            name
            age = 18
            // 这个是构造器,创建对象的时候默认调用这个方法去初始化
            constructor(name){
                this.name = name
            }
            // 两个公有方法
            sayHi(){
                console.log('嗨!你好!');
            }
            sayMyself(){
                console.log('我的名字是:' + this.name + '。我的年龄是:' + this.age);
            }
        }

        const p1 = new person('张三')
        p1.sayHi()
        p1.sayMyself()
    </script>

2、calss的继承

关键字介绍:

  • extendx:用于类声明或者类表达式中,以创建一个类,该类是另一个类的子类
  • super:关键字用于访问对象字面量或类的原型([[ prototype ]])上的属性,或调用父类的构造函数

这里我们可以看到,一个Student类继承了person。并且有了自己的age属性以及继承的name属性。在子类的构造器中传入了两个参数,并且调用了父类的构造器,修改了name的值。在子类的构造器中修改了age的值。而后去实例化对象,调用父类的方法,实现数据的输出。

javascript 复制代码
    <script>
        class person{
            // 这是公有属性
            name
            // 这个是构造器,创建对象的时候默认调用这个方法去初始化
            constructor(name){
                this.name = name
            }
            // 两个公有方法
            sayHi(){
                console.log('嗨!你好!');
            }
            sayMyself(){
                console.log('我的名字是:' + this.name + '。我的年龄是:' + this.age);
            }
        }
        // Student子类继承了person父类
        class Student extends person{
            // 子类里的公有属性
            age
            // 子类的构造器
            constructor(name,age){
                // 调用父类的构造函数,必须放在  使用this 以前
                super(name)
                this.age = age
            }
        }

        const p2 = new Student('李四',20)
        p2.sayHi()
        p2.sayMyself()
    </script>

注意:如果父类有构造器,子类必须调用 super 关键字,而且要在 this 前使用。同时子类和父类的方法如果重名,那么默认子类覆盖父类的重名方法。

3、静态属性和私有属性

关键字介绍

  • 静态:类(Class)通过static关键字定义静态方法。不能在类的实例上调用静态方法,只能通过类本身调用(className.method())
  • 私有:类属性默认是公有的,可以使用哈希前缀 # 的方法将其定义为私有,声明和访问的时候也需要加上。

这里我们可以看到,由于 person 中的 age 是静态的,所以我们只能通过其本身来访问。

而#address是私有的,我们无法访问,因此想要访问只能提供一个 getter 方法,即getAddress()方法来访问。

javascript 复制代码
    <script>
        class person{
            // 这是公有属性
            name
            // 这是静态属性
            static age = 18
            // 这是私有属性
            #address = '贵阳XXXXXX'
            // 这个是构造器,创建对象的时候默认调用这个方法去初始化
            constructor(name){
                this.name = name
            }
            // 静态方法
            static sayHi(){
                console.log('嗨!你好!');
            }
            //公有方法
            sayMyself(){
                console.log('我的名字是:' + this.name);
            }
            getAddress(){
                console.log(this.#address);
            }
        }

        console.log('静态属性只能通过本身来访问' + person.age);
        person.sayHi()


        const p3 = new person('张三')
        p3.sayMyself()
        // 私有属性需要getter来访问
        p3.getAddress()
    </script>

4、寄生组合式继承(ES5)

上面的三个都是在ES6中所出现的基于Class实现继承。而在ES5中同样也有实现继承的方法,比如原型链继承,组合继承等六种方式。那么在这里我将不会一一详解,只把我个人感觉使用最多,最重要的寄生组合式继承放在这里简要说明一下。

注意:在ES6中基于class实现的继承,其原理也是寄生组合式继承。

寄生组合式继承:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

知识点介绍:Objcet.create(源对象,要覆盖的属性/方法):将一个对象作为原型,创建一个新的对象。

下面这个代码,是 定义了一个 Person 父类,和 Student 子类。在这里,子类通过构造函数继承属性。而方法是使用的 Object.create() 来获取了一个 prototype 并且改变了其构造器的指向,然后赋给了子类。

javascript 复制代码
    <script>
        // 父类
        function Person(name){
            this.name = name
        }
        Person.prototype.sayHi =function () {
            console.log(`你好,我叫:${this.name}`);
        }
        // 通过构造函数继承属性
        function Student(name){
            Person.call(this,name)
        }
        // 通过原型链继承方法,第二个参数是改变构造函数的指向
        const prototype = Object.create(Person.prototype,{
            constructor:{
                value:Student
            }
        })

        // 将创建的原型赋给Student
        Student.prototype = prototype

        const s = new Student('王五')
        console.log(s);
    </script>

三:总结

掌握继承的原理和在ES6中的实现,是非常重要的,虽然看似简单,使用起来也简单,但是只有当你真正的明白了代码在内部是如何运转的,才能够在以后面对各种突发情况的时候知道解决的办法。因此让我们一起来学习与使用这些宝贵的知识吧!

相关推荐
Swift社区1 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
new出一个对象1 小时前
uniapp接入BMapGL百度地图
javascript·百度·uni-app
没头脑的ht1 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht1 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20241 小时前
Swift 数组
开发语言
你挚爱的强哥2 小时前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
stm 学习ing2 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
y先森2 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy2 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189113 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js