类描述了所创建的对象共同的属性和方法。
最基本的类 1 2 3 4 5 6 7 8 9 // ts class Person<T> {} // 编译成js后 var Person = /** @class */ (function () { function Person() { } return Person; }());
简单使用 定义类的关键字为 class,后面紧跟类名,类可以包含以下几个模块(类的数据成员):
字段:字段是类里面声明的变量。字段表示对象的有关数据。
构造函数:类实例化时调用,可以为类的对象分配内存。
方法:方法为对象要执行的操作。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 29 30 // ts class Person<T> { // 字段 name: string // 构造函数 constructor(name: string) { this.name = name } // 方法 getName() { return this.name } } const person = new Person('老王') console.log(person.getName()) // 老王 // 编译成js后 var Person = /** @class */ (function () { // 构造函数 function Person(name) { this.name = name; } // 方法 Person.prototype.getName = function () { return this.name; }; return Person; }()); var person = new Person('老王'); console.log(person.getName());
new 关键字我们使用 new 关键字来实例化类的对象,类实例化时会调用构造函数,类中的字段属性和方法可以使用 . 号来访问。完整实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Person<T> { // 字段 name: string // 构造函数 constructor(name: string) { this.name = name } // 方法 getName() { return 'getName: ' + this.name } } // 创建一个对象 const person = new Person('老王') // 访问字段 console.log(person.name) // 老王 // 访问方法 console.log(person.getName()) // getName: 老王
类的继承 顾名思义,子类继承父类后,可以使用父类的属性和方法。但是要注意的是,子类只能继承一个父类,TypeScript 不支持继承多个类,但支持多重继承。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Person<T> { name: string age: number constructor(name: string, age: number) { this.name = name this.age = age } } class Info extends Person<unknown> { sex: string constructor(name: string, age: number, sex: string) { super(name, age) this.sex = sex } getInfo() { return `姓名:${this.name},年龄:${this.age},性别:${this.sex}` } } const info = new Info('翠花', 18, '女') console.log(info.getInfo()) // 姓名:翠花,年龄:18,性别:女
多重继承
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 class Person<T> { name: string age: number constructor(name: string, age: number) { this.name = name this.age = age } } class Like extends Person<unknown> { mylike: string constructor(name: string, age: number, mylike: string) { super(name, age) this.mylike = mylike } } class Info extends Like { sex: string constructor(name: string, age: number, mylike: string, sex: string) { super(name, age, mylike) this.sex = sex } getInfo() { return `姓名:${this.name},年龄:${this.age},性别:${this.sex},爱好:${this.mylike}` } } const info = new Info('翠花', 18, '游泳', '女') console.log(info.getInfo()) // 姓名:翠花,年龄:18,性别:女,爱好:游泳
继承类的方法重写 子类得到父类的属性和方法后,我们相当于继承了父类的财产,那么在没有任何约束的情况下,我们就可以按照自己的意愿来使用这笔财产,在遇到父类和我们在使用这笔财产做法有出入时,我们便可以按照自己的方法来操作。这个过程称之为方法的重写。
1 2 3 4 5 6 7 8 9 10 11 12 class Father<T> { loveFn() { console.log('我是父类,我爱喝红牛') } } class Son extends Father<unknown> { loveFn() { console.log('我是子类,我爱喝饮料') } } const son = new Son() son.loveFn() // 我是子类,我爱喝饮料
如果我们想要引用父类的属性和方法,可以使用 super 关键字。
1 2 3 4 5 6 7 8 9 10 11 12 13 class Father<T> { loveFn() { console.log('我是父类,我爱喝红牛') } } class Son extends Father<unknown> { loveFn() { super.loveFn() console.log('我是子类,我爱喝饮料') } } const son = new Son() son.loveFn() // 我是父类,我爱喝红牛 我是子类,我爱喝饮料
static 关键字 static 关键字用于定义类的数据成员(属性和方法)为静态的,静态成员可以直接通过类名调用。
1 2 3 4 5 6 7 8 class Person<T> { static person_name: string static getName() { return Person.person_name } } Person.person_name = '翠花' console.log(Person.getName()) // 翠花
instanceof 运算符 instanceof 运算符用于判断对象是否是指定的类型,如果是返回 true,否则返回 false。
1 2 3 class Person<T> {} const person = new Person() console.log(person instanceof Person) // true
访问控制修饰符 TypeScript 支持 3 种不同的访问权限:
public(默认):公有,可以在任何地方被访问。
protected:受保护,可以被其自身以及其子类访问。
private:私有,只能被其定义所在的类访问。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Person<T> { public name: string = '老王' private age: number = 30 protected sex: string = '男' getAge() { return this.age } } class Sex extends Person<unknown> { getSex() { return this.sex } } const person = new Person() console.log(person.name) // 老王 // console.log(person.age) // 报错,私有属性,只能在Person类中访问 console.log(person.getAge()) // 30 // console.log(person.sex) // 报错,保护属性,只能在Person类或Sex中访问 const sex = new Sex() console.log(sex.getSex()) //男
类和接口 类使用关键字 implements 实现接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 interface Info { name: string, age: number } class Person implements Info { name: string age: number sex: string constructor(name: string, age: number, sex: string) { this.name = name this.age = age this.sex = sex } getInfo() { return `姓名:${this.name},年龄:${this.age},性别:${this.sex}` } } const person = new Person('翠花', 18, '女') console.log(person.getInfo()) // 姓名:翠花,年龄:18,性别:女
获取器/设置器
如果 get 存在但没有 set,则属性自动为 readonly 如果不指定 setter 参数的类型,则从 getter 的返回类型推断 getter 和 setter 必须有相同的 成员可见性
1 2 3 4 5 6 7 8 9 10 11 12 class Person { _name: string get name() { return this._name } set name(n:string) { this._name = n } } const person = new Person() person.name = '老王' console.log(person._name) // 老王
static类中的块 静态块允许你编写具有自己作用域的语句序列,这些语句可以访问包含类中的私有字段。这意味着我们可以编写具有编写语句的所有功能的初始化代码,不会泄漏变量,并且可以完全访问我们类的内部结构。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Person { static _name: string get name() { return Person._name } set name(n: string) { Person._name = n } static { console.log('static类中的块') Person._name = '老王' } } const person = new Person() console.log(person.name) // 老王 person.name = '翠花' console.log(person.name) // 翠花
抽象类 在TypeScript中,可以使用 abstract 关键字来定义抽象类和抽象方法。抽象类不能被直接实例化,它只能被用作其他类的基类。抽象方法是没有实现的方法,必须在子类中被重写。
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 // 抽象类 abstract class A { // 抽象属性 abstract name: string // 抽象方法 abstract getName(): void // 具体方法 setName(name: string) { this.name = name } } class B extends A { name: string constructor(name: string) { super() this.name = name } getName(): string { return this.name } } const b = new B('老王') console.log(b.getName()) // 老王 b.setName('翠花') console.log(b.getName()) // 翠花
小技巧 在以上方法中我们一直都使用构造函数初始化,如果我们不想在构造函数中初始化,可以找到 typescript 的配置文件 tsconfig.json 中的 strictPropertyInitialization,将其改为 false 即可。
1 2 3 4 class Person { name: string age: number }