Skip to content
目录

基础篇-类

TypeScript 中的类与 ES2015 几乎是一样的,主要区别是在于类成员的访问修饰符

ES6 中类的用法

属性和方法
使用 class 定义类,使用 constructor 定义构造函数。 通过 new 生成新实例的时候,会自动调用构造函数。

js
class Animal {
  constructor(name) {
    this.name = name;
  }
  sayHi() {
    return `My name is ${this.name}`;
  }
}

let a = new Animal('Jack');
console.log(a.sayHi()); // My name is Jack

类的继承
使用 extends 关键字实现继承,子类中使用 super 关键字来调用父类的构造函数和方法。

js
class Cat extends Animal {
  constructor(name) {
    super(name); // 调用父类的 constructor(name)
    console.log(this.name);
  }
  sayHi() {
    return 'Meow, ' + super.sayHi(); // 调用父类的 sayHi()
  }
}

let c = new Cat('Tom'); // Tom
console.log(c.sayHi()); // Meow, My name is Tom

存取器
使用 getter 和 setter 可以改变属性的赋值和读取行为

js
class Animal {
  constructor(name) {
    this.name = name;
  }
  get name() {
    return 'Jack';
  }
  set name(value) {
    console.log('setter: ' + value);
  }
}

let a = new Animal('Kitty'); // setter: Kitty
a.name = 'Tom'; // setter: Tom
console.log(a.name); // Jack

静态方法

使用 static 修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用

js
class Animal {
  static isAnimal(a) {
    return a instanceof Animal;
  }
}

let a = new Animal('Jack');
Animal.isAnimal(a); // true
a.isAnimal(a); // TypeError: a.isAnimal is not a function

es6 中的 class 类

ES7 中类的用法

实例属性
ES6 中实例的属性只能通过构造函数中的 this.xxx 来定义,ES7 提案中可以直接在类里面定义

js
class Animal {
  name = 'Jack';

  constructor() {
    // ...
  }
}
let a = new Animal();
console.log(a.name); // Jack

静态属性

ES7 提案中,可以使用 static 定义一个静态属性

js
class Animal {
  static num = 42;

  constructor() {
    // ...
  }
}

console.log(Animal.num); // 42

TS 中类的用法

TypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 publicprivateprotected

  • public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
  • private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
  • protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的
  • readonly 只读属性必须在声明时或构造函数里被初始化

public

public 访问修饰符

在类里面、 子类 、类外面都可以访问

js
class Person {
     constructor(name: string) {
    }
}
const user = new Person('');
console.log(user.name) //类型“Person”上不存在属性“name”

//可以在类上挂载
class Person {
     name:string;
     constructor(name: string) {
       this.name=name
    }
}
const user = new Person('');
console.log(user.name) //王

//public 可以在类上挂载
class Person {
     constructor(public name: string) {
    }
}
const user = new Person('');
console.log(user.name) //王

上面的例子中,name 被设置为了 public,所以直接访问实例的 name 属性是允许的。
很多时候,我们希望有的属性是无法直接存取的,这时候就可以用 private 了:

private

private 修饰符

在类里面可以访问,子类、类外部都没法访问
当成员被标记成 private 时,就不能在声明它的类的外部访问

js
class Person {
    private name: string;
    public constructor(name: string) {
        this.name = name;
    }
    getName(): string {
        return this.name;
    }
    setName(name: string): void {
        this.name = name;
    }
}

const user = new Person('');
user.setName('');
console.log(user.name); //private 直接访问实例的name 报错
console.log(user.getName());

使用 private 修饰的属性或方法,在子类中也是不允许访问的

js
class Xiao extends Person {
  constructor(name: string) {
    super(name);
    console.log(this.name); //报错
  }
}

对构造函数加上 private,则这个类既不能实例化也不可以继承

js
class Person {
  private name: string;
  private constructor(name: string) {
    this.name = name;
  }
  getName(): string {
    return this.name;
  }
  setName(name: string): void {
    this.name = name;
  }
}

const user = new Person(""); //报错
class Xiao extends Person {}//报错

protected

protected 访问修饰符

在类里面、子类里面可以访问 ,实例化没法访问
如果是用 protected 修饰,则允许在子类中访问:

js
class Person {
    protected name: string;
    public constructor(name: string) {
        this.name = name;
    }
    getName(): string {
        return this.name;
    }
    setName(name: string): void {
        this.name = name;
    }
}

class Xiao extends Person {
    constructor(name: string) {
        super(name);
        console.log(this.name); //子类中可以访问
    }
}

let xiaoming = new Xiao('小明');  //小明
console.log(xiaoming.name); //实例中报错
console.log(xiaoming.getName()); //小明

readonly

readonly 修饰符

js
class Animal {
    readonly name = '老外';
    public constructor(name) {
        this.name = name;
    }
}

let cat = new Animal('mao');
cat.name = '老毛'; //报错

static

只能通过类或子类访问,实例无法访问

js
class Animal {
  public name: string = "老外";
  public constructor(name: string) {
    this.name = name;
  }
  static age: number = 12;
}

let cat = new Animal("mao");
console.log(Animal.age);//类访问
console.log(cat.age); //实例无法访问

参数属性

参数属性通过给构造函数参数添加一个访问限定符来声明。 使用 private 限定一个参数属性会声明并初始化一个私有成员;对于 public 和 protected 来说也是一样。

js
class Animal {
  public constructor(name: string) {}
  static age: number = 12;
}
let cat = new Animal("mao");
console.log(cat);//Animal {}

在构造函数加修饰符

js
class Animal {
  public constructor(public  name: string) {}
  static age: number = 12;
}
let cat = new Animal("mao");
console.log(cat);//Animal {name: "mao"}

abstract 抽象类

抽象类
abstract 用于定义抽象类和其中的抽象方法,有利于代码复用和扩展。 什么是抽象类 首先,抽象类只能被继承不能被实例化的类:

js
abstract class Animal {
    public name;
    public constructor(name) {
        this.name = name;
    }
    public abstract sayHi();
}

let a = new Animal('Jack');

// index.ts(9,11): error TS2511: Cannot create an instance of the abstract class 'Animal'.

上面的例子中,我们定义了一个抽象类 Animal,并且定义了一个抽象方法 sayHi。在实例化抽象类的时候报错了。 其次,抽象类中的抽象方法必须被子类继承实现:

js
abstract class Animal {
    public name;
    public constructor(name) {
        this.name = name;
    }
    public abstract sayHi();
}

class Cat extends Animal {
    public eat() {
        console.log(`${this.name} is eating.`);
    }
}

let cat = new Cat('Tom');

// index.ts(9,7): error TS2515: Non-abstract class 'Cat' does not implement inherited abstract member 'sayHi' from class 'Animal'.

上面的例子中,我们定义了一个类 Cat 继承了抽象类 Animal,但是没有实现抽象方法 sayHi,所以编译报错了。 下面是一个正确使用抽象类的例子

js
abstract class Animal {
    public name;
    public constructor(name) {
        this.name = name;
    }
    public abstract sayHi();
}

class Cat extends Animal {
    public sayHi() {
        console.log(`Meow, My name is ${this.name}`);
    }
}

let cat = new Cat('Tom');

上面的例子中,我们实现了抽象方法 sayHi,编译通过了

类的类型

给类加上 TypeScript 的类型很简单,与接口类似

js
class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  sayHi(): string {
    return `My name is ${this.name}`;
  }
}

let dog: Animal = new Animal('Jack');
console.log(dog.sayHi()); // My name is Jack

类实现接口

类实现接口