• ES6 类


    前言

    JavaScript在 ES6 引入的类的概念无疑让这门语言拥有了更贴近于传统面向对象编程语言的编写模式

    类的声明

    ES6引入了 class 关键字来进行类的声明,类的声明可以直接使用class关键字和类名组合声明,也可以是使用表达式的形式声明。

    1、类声明和即将要讲解的类表达式都不会被提升;
    2、类中的代码在执行时,会强制开启严格模式;
    3、类的所有方法都不可枚举,并且不能与new组合使用。

    使用class关键字和类名直接声明

     // 在ES5及以前中,没有类的概念,通过构造函数和原型混合模拟定义‘类’,转化一下的写法如下
    // function Person(aAge, aName) {
    //     this.age = aAge;
    //     this.name = aName;
    // }
    // Person.prototype.showName = function () {
    //     console.log(this.name);
    // }
    
    // 类的声明
    class Person {
    	// 构造函数
        constructor(aAge, aName) {
            this.age = aAge;
            this.name = aName;
        }
        // 等同于Person.prototype.showName
        showName(){
            console.log(this.name);
        }
    }
    
    // 执行输出:Bob
    let person = new Person(18, 'Bob');
    person.showName();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    表达式声明

    let Person = class {
    	// 构造函数
        constructor(aAge, aName) {
            this.age = aAge;
            this.name = aName;
        }
        // 等同于Person.prototype.showName
        showName(){
            console.log(this.name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 每个类有且只有一个构造函数:constructor(),如果未显式声明,则默认一个空的构造函数以供调用(与C++类似)。
    • 类的使用consturctor方法名字定义构造函数
    • 自有(私有)属性和方法一般在consturctor中定义

    类的成员

    类的成员包含普通的原型方法或自有属性,还有特殊功能的构造函数、生成器、静态方法和访问器属性等,并且成员名可以是表达式。

    自有属性

    类中的自有属性一般在构造函数中执行初始化。

    class People {
      constructor() {
        this.name = "Bob";
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    访问器属性

    访问器属性通过关键字 getset 创建,可以用来控制属性的读写。

    class Person {
        constructor(aAge, aName) {
            this._age = aAge;
            this._name = aName;
        }
        showName() {
            console.log(this.name);
        }
        // age 可以读写
        get age() {
            return this._age;
        }
        set age(value) {
            this._age = value;
        }
        // name只读
        get name() {
            return this._name;
        }
    }
    
    let person = new Person(18, 'Bob');
    console.log(person.age); // 18
    person.age = 20;
    console.log(person.age);// 20
    console.log(person.name); // Bob
    person.name = 'CP';
    console.log(person.name);// Bob
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    静态方法

    ES6新增了static关键字,可把类中的方法(除了构造函数)定义成静态的,注意ES6无静态属性,只有静态方法。

    class Person {
    	// 构造函数
        constructor(aAge, aName) {
            this.age = aAge;
            this.name = aName;
        }
        static sTest(){
            console.log('sTest');
        } 
    }
    Person.sTest(); // sTest
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    类的继承

    ES6提供了 extends 关键字实现类的继承。
    代码示例:Student类通过关键字 extends 继承Person类,Student类称为派生类,Person类称为基类。

    class Person {
        constructor(aAge, aName) {
            this.age = aAge;
            this.name = aName;
        }
        run() {
            console.log(this.name + ' is running...');
        }
    }
    
    class Student extends Person{
        constructor(aAge, aName, aId){
            super(aAge, aName);
            this.id = aId;
        }
    }
    
    let student = new Student(18, 'Bob','001');
    student.run(); //Bob is running...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 派生类定义了构造函数,则必需且需要在this之前调用super();
    • 派生类没有定义构造函数,在派生类实例化的时候实例会自动调用super()并传入所有参数;
    class Person {
        constructor(aAge, aName) {
            this.age = aAge;
            this.name = aName;
        }
        run() {
            console.log(this.name + ' is running...');
        }
    }
    
    class Teacher extends Person {
        // 无构造函数
    }
    
    // 等价于
    // class Teacher extends Person{
    //     constructor(...args){
    //         super(...args)
    //     }
    // }
    let teacher = new Teacher(28, 'CP', '002');
    teacher.run(); // CP is running...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 派生类中可以重写基类的方法
    class Person {
        constructor(aAge, aName) {
            this.age = aAge;
            this.name = aName;
        }
        run() {
            console.log(this.name + ' is running...');
        }
    }
    
    class Student extends Person {
        constructor(aAge, aName, aId) {
            super(aAge, aName);
            this.id = aId;
        }
        // 覆盖Person.prototype.run()方法
        run() {
            console.log(this.id + this.name + ' is running...');
        }
    }
    let student = new Student(18, 'Bob', '001');
    student.run();// 001Bob is running...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 派生类中可以用super调用基类方法
    class Person {
        constructor(aAge, aName) {
            this.age = aAge;
            this.name = aName;
        }
        run() {
            console.log(this.name + ' is running...');
        }
    }
    
    class Student extends Person {
        constructor(aAge, aName, aId) {
            super(aAge, aName);
            this.id = aId;
        }
        study() {
            super.run();
            console.log(this.name + ' is studying...');
        }
    }
    let student = new Student(18, 'Bob', '001');
    student.study();
    //Bob is running...
    //Bob is studying...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    笛卡尔树—简介
    在线问诊 Python、FastAPI、Neo4j — 构建问题分类器
    Qt-键盘消息的传递-键盘消息的获取-C++
    【项目实战】多租户实现数据库动态切换
    Ubuntu 22.04 搭建 KubeSphere 3.4.1 集群
    R语言筛选时间序列数据的子集(subset time series data)、构建单个日期时间索引数据筛选时间序列数据指定索引对应的数值
    数据库的下一个变革方向——云原生数据库
    《深度学习进阶:自然语言处理》读书笔记:第7章 基于RNN生成文本
    什么是数据中台,关于数据中台的6问6答6方法
    Thrift、Dubbo、Spring Cloud 和 gRPC
  • 原文地址:https://blog.csdn.net/Mr_Bobcp/article/details/126075869