一、认识类

在早期的JavaScript开发中(ES5)需要通过函数和原型链来实现类和继承

从ES6开始,引入了class关键字,可以更加方便的定义和使用类。

TypeScript作为JavaScript的超集,也是支持使用class关键字的,并且还可以对类的属性和方法等进行静态类型检测

实际上在JavaScript的开发过程中,我们更加习惯于函数式编程:

  • 比如React开发中,目前更多使用的函数组件以及结合Hook的开发模式
  • 比如在Vue3开发中,目前也更加推崇使用 Composition API

但是在封装某些业务的时候,类具有更强大封装性,所以我们也需要掌握它们

  • 类的定义我们通常会使用class关键字
  • 在面向对象的世界里,任何事物都可以使用类的结构来描述
  • 类中包含特有的属性和方法

二、类的定义

定义一个Person类: 使用class关键字来定义一个类

我们可以声明一些类的属性:

在类的内部声明类的属性以及对应的类型,如果类型没有声明,那么它们默认是any的

我们也可以给属性设置初始化值

在默认的strictPropertyInitialization模式下面我们的属性是必须初始化的,如果没有初始化,那么编译时就会报错

  1. class Person {
  2. name: string;
  3. age: number;
  4. say() {
  5. console.log(`Hello,${this.name}`);
  6. }
  7. }

5、TypeScript-类的使用 - 图1

如果我们在strictPropertyInitialization模式下确实不希望给属性初始化,可以使用 name!: string语法

类可以有自己的构造函数constructor,当我们通过new关键字创建一个 实例时,构造函数会被调用

构造函数不需要返回任何值,默认返回当前创建出来的实例

类中可以有自己的函数,定义的函数称之为方法

  1. class Person {
  2. // 赋初始值
  3. // name: string = '';
  4. // age: number = 20;
  5. name: string;
  6. age: number;
  7. // 使用constructor
  8. constructor(name: string, age: 20) {
  9. this.name = name;
  10. this.age = age;
  11. }
  12. say() {
  13. console.log(`Hello,${this.name}`);
  14. }
  15. }
  16. let p = new Person('xxx', 20);

三、类的特性

继承

面向对象的其中一大特性就是继承,继承不仅仅可以减少我们的代码量,也是多态的使用前提

我们使用extends关键字来实现继承,子类中使用super来访问父类

看一下Student类继承自Person:

Student类可以有自己的属性和方法,并且会继承Person的属性和方法

在构造函数中,我们可以通过super来调用父类的构造方法,对父类中的属性进行初始化;

  1. class Person {
  2. name: string;
  3. age: number;
  4. constructor(name: string, age: number) {
  5. this.name = name;
  6. this.age = age;
  7. }
  8. eating() {
  9. console.log('eating');
  10. }
  11. }
  12. class Student extends Person {
  13. son: number;
  14. constructor(name: string, age: number, son: number) {
  15. // super调用父类构造器
  16. super(name, age);
  17. this.son = son;
  18. }
  19. // 重写 overwrite
  20. eating() {
  21. // 调用父类方法
  22. super.eating();
  23. console.log('student eating');
  24. }
  25. }
  26. const stu1 = new Student('yyy', 20, 111);
  27. console.log(stu1.name); // yyy
  28. console.log(stu1.age); // 20
  29. stu1.eating(); // eating //student eating

多态

父类或者接口定义的引用变量可以指向子类或者具体实现类的实例对象

由于程序调用方法是在运行期才动态绑定的,那么引用变量所指向的具体实例对象在运行期才确定

所以这个对象的方法是运行期正在内存运行的这个对象的方法而不是引用变量的类型中定义的方法。

  1. class Animals {
  2. action() {
  3. console.log('action');
  4. }
  5. }
  6. class Dog {
  7. action() {
  8. console.log('dog running');
  9. }
  10. }
  11. class Fish {
  12. action() {
  13. console.log('fish swimming');
  14. }
  15. }
  16. function moveAction(animals: Animals[]) {
  17. animals.forEach((animal) => {
  18. animal.action();
  19. });
  20. }
  21. //dog running fish swimming
  22. moveAction([new Dog(), new Fish()]);
  23. //多态:父类引用指向子类实例对象