blog

类,具有静态属性、属性、方法、静态方法,是 js 从语言层面上正式面向对象编程的一大步

类的语法是 es6 才的语法,当我们在代码中写类后,一般需要通过 babel 将其转化为 es5 的代码, 转换出来的代码就是使用原型以及原型链来实现的,有兴趣的伙伴可以看看 class 转换后的实现代码

如果对于类来说并不了解的话,可以去看看阮一峰老师的 es6 或者 MDN

语法

class ClassName {}

// 需要继承一个类时
class ClassName extends ClassParent {}

// class 的 constructor 函数
class ClassName {
    // 接受外部传入的参数
    // 在 constrcutor 函数执行的时候,它的方法和属性都已经挂载完毕,可以直接使用
    constructor(...arg: unknown[]) {}
}

ts 类 的作用

  1. 可实例化的类
  2. 提供一个类型
  3. 可抽像

1. 产出可实例化的类

这点大家都懂,不过避免误解为的话,大家还是看码吧

class Person {
    constructor() {
        // xxx
    }
}

// 可实例化的类
const person = new Person();

提供一个类型

class 如过砍掉了实例化功能,那么就跟 interface 很像了

class 在可以实例化的同时可以当作类型使用,当然,当作类型时,在转换为 js 时都会删干净的

class Person {}

class Supermen extends Person {
    constructor(name: string, age: number) {}
}

// person 可能会是 Supermen 或 Person 两个类的实例
const person: Supermen | Person | undefined;

// 你有10%的几率出生为超人,否则就成为普通人吧
if (Math.random() < 0.1) {
    person = new Supermen('shange', 19);
} else {
    person = new Person();
}

可抽象

抽象是在 ts 是什么意思?

直接看以下示例代码吧

/**
 * 现在导航栏,导航栏中有很多button,这些button不仅仅我们内置的几个,还得外部能扩展
 * 我们需要把这个button类让外部使用,但是还得让外部知道我们这里有那些方法是在扩展时是自己必须要实现的
 */
abstract class ButtonExtend {
    // 不抽象属性,当子级实例化后可直接使用
    el: HTMLElement = document.createElement('button');
    constructor() {
        this.el.style.cssText = this.getStyle();
        this.el.addEventListener('click', this.onClick.bind(this));
    }

    // 限制返回字符串css样式
    abstract getStyle(): string;
    // 限制必须有onClick事件
    abstract onClick(event: Event): void;
}

// 外部扩展时
class Button extends ButtonExtend {
    onClick(e: Event) {
        // xxxx
    }

    getStyle() {
        return 'width: 100px';
    }
}

看完上面是不是有些懵

懵的话就对了,我们来一个一个解读

abstract 抽象

知道这个单词会知道,它翻译成中为就是抽象,那么加在 class 前,我们就可以称呼这个类叫做抽象类

抽象类,类如其名,它是抽象的,特点就是不能被直接实例化,只能作为一个类型或者父类来使用

class 前 abstract 叫抽象类,那么内部的方法前面带上它就可以叫做是抽象方法抽象属性

abstract 的类在被继承(extends)后,会要求子类实现抽线的属性,方法

implements 实现

// 库内部
class WorkerHandler {
    id: number;

    run(): void {}
}

class WorkerContainer {
    queue: WorkerHandler[] = [];
    constructor() {}

    addWorker(w: WorkerHandler) {
        this.queue.push(w);
    }
}

// 用户使用
const container = new WorkerContainer();

class CompareWorker implements WorkerHandler {
    id: 0;

    run() {
        console.log(1 + 2);
    }
}

翻译成中文叫做 实现,顾名思义,实现 implements 类中的属性、方法都需要被实现一边

implements 可以引入一个或多个类(不抽象的类也可以,但没啥作用,还要多写一遍引入类的代码)

不实现会怎么样(也就编译失败而已啦

implements 常用于限制参数或返回值的类型,使得它们存在一些我们需要的 方法属性

可用于类的关键字

abstractpublicprivateprotected,这些关键字可用于类中的方法或属性

class Person {
    public name: string = 'shang';

    private age: number = 18;

    protected heigth: number = 180;

    constructor() {
        this.name;
    }
}

class SupermenPerson extends Person {
    constructor() {
        super();
        this.age; // error
        this.heigth; // success
        this.name; // success
    }
}

const person = new SupermenPerson();
person.age; // error
person.heigth; // error
person.name; // success

public

无论是子类还是实例化后,都能访问这个属性,这个属性也是默认的

private

只有在本类中中才能访问,子类和实例化后都不可以

protected

protected 子类和父类都可以获取这个属性,但是实例化后实例(也就是类外部)不能访问

与 private 的区别就是子类可以访问此属性

关键字的特殊作用

在类中的参数列表中,在参数前面添加关键字,可以使参数直接放置到 this 上

class Person {
    constructor(public name: string, private age: number, protected heigth: number) {
        this.name; // success
        this.age; // success
        this.heigth; // success
    }
}