为了后续内容(如nestjs
等框架)的开展,本文更新TS相关的基础知识。typescript
关注获取更多TS精品文章
缓存
传统JS使用函数
和原型链
进行集成,在ES6
出现了class
关键,JS也能使用传统OOP的方式进行继承,可是仍是存在必定的局限性,在TS中,OOP已经和传统语言差很少。微信
class Parent { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } say() { return `name: ${this.name}, age: ${this.age}`; } } const parent = new Parent(); parent.say();
能够看到TS的OOP写法和Java仍是有点相似的。可是他两的构造方法名不一样,TS构造方法名为constructor
,Java是类名
。框架
继承用来扩展示有的类,TS中这一点和传统语言同样使用extends
语法。函数
class Parent { name: string; constructor(name: string) { this.name = name; } say() { console.log(`Parent say: ${this.name}`); } } class Child extends Parent { age: number; constructor(name: string, age: number) { // 覆盖父类构造方法 super(name); // 调用父类构造方法 this.age = age; } say() { console.log(`Child say: ${this.name} ${this.age}`); } } const child: Parent = new Child("haha" ,1); child.say(); // 输出 Child say haha 1
显示调用
父类构造方法先有父亲,后有儿子
值
而不是基于类型声明
,好比child
声明为Parent
类型,可是值是子类型,因此调用方法时会调用子类
的say
TS中方法和属性默认的访问限定符为public
,全部外部或内部成员均可访问。this
class Parent { public name: string; // public能够不加 say() { console.log(`say ${this.name}`); } } const p = new Parent(); p.name = 'hello'; p.say(); // 输出 say hello
私有访问,只能在本类
访问,子类和其余类都不行
。spa
class Parent { private name: string; private say() { console.log(`say ${this.name}`); } } const p = new Parent(); p.name = 'hello'; // 错误,private限定的属性不能被外部访问 p.say(); // 错误,private限定的访问不能被外部访问
保护性访问,只能被本类或本类的子类(子类的子类也能够访问)
。code
class Parent { protected name: string; constructor(name: string) { this.name = name; } protected say() { console.log(`say ${this.name}`); } } class Child extends Parent { public say() { // 提高访问性 console.log(`say ${this.name}`); // 访问父类属性 } } const c = new Child('hello'); c.say(); // 输出 say hello
访问限定符只能提高,不能下降,以下例子是没法经过编译的
:对象
class Parent { protected name: string; } class Child extends Parent { private name: string; // 错误,子类访问性必须>=父类的访问性 }
TS使用readonly
声明只读属性(方法不能使用)
,必须在声明时
或者构造时
进行赋值,其余地方不能赋值
继承
class Parent { private readonly name = 'hello'; private readonly age: number; constructor(age: number) { this.age = age; } }
在上例中咱们在构造方法中使用this.age = age
对已存在的私有只读属性age
进行了赋值。因为该操做时经常使用操做,因此TS有了更加便捷的写法:
class Parent { constructor(readonly name: string, private readonly age: number) { } say() { console.log(`say ${this.name} ${this.age}`); } }
上例中声明了公有只读的name属性,私有只读的age属性
在传统语言中,几乎不会直接声明公有属性,而后对其进行操做,都会先定义私有属性,而后提供getter
和setter
方法对其操做(Java中不少类都是这种状况
)
class Parent { private _name: string; get name(): string { return this._name; } set name(name: string) { console.log(`name设置前: ${this._name} 设置后: ${name}`); this._name = name; } } const parent = new Parent(); parent.name = 'ok'; // 能够直接使用赋值语句,可是会自动调用set name(name: string)方法
getter和setter方法提升了开发者对属性的控制,一块儿对属性的访问都是可控的,为之后的扩展性打下了基础(好比若是须要加缓存,咱们能够在set时设置缓存,get时读取缓存,若是是直接操做属性的话,该功能实现起来很麻烦
以上讨论的都是实例属性和梳理方法
,须要有实例才能调用,若是有些属性或方法并非存在于实例上时可使用静态方法或静态属性
class Parent { static name: string; static say() { console.log(`name ${this.name}`); // 方法是静态,属性是静态时可使用this } } Parent.say();// 使用类名调用静态方法
须要注意的是实例能够直接调用静态,静态不能直接调用实例
,由于实例须要实例化后调用
传统语言中接口只包含实现,不包含细节。而抽象类能够包含细节。通常来讲,有些公有方法能够放到抽象类作,不一样的子类完成不一样功能的代码能够放到抽象类作。
abstract class Animal { abstract say(): void; // 声明抽象方法,子类必须实现 eat() { console.log(`animal eat`); } } class Human extends Animal { // 使用extends关键字 say() { console.log('human say words'); } } class Dog extends Animal { say() { console.log('dog say wangwang'); } }
接口用来限定子类的行为,不关心具体实现。与传统语言不一样的是,TS接口还能够限定变量或常量的属性
限定子类行文:
interface Animal { say(): void; eat(): void; } class Human implements Animal { say() { console.log('human say'); } eat() { console.log('human eat'); } }
限定变量属性:
interface A { name?: string; age: number; } const obj: A = { age: 10, // name是可选的 };
使用可索引类型
来描述
能够经过索引访问获得
的类型。如person["name"]
,list[0]
interface HashMap { [key: string]: any; // 冒号左边为属性名类型,右边为值类型 } const map: HashMap = {}; map["name"] = "1"; map.a = "2";
与类继承相似,接口也能够经过继承来扩展示有的功能:
interface Animal { eat(): void; // 动物会吃,可是怎么吃的无论 } interface Human extends Animal { say(): void; // 人会说话,可是怎么说,说什么无论 }
JS中,函数能够直接调用也能够经过对象方式调用,TS中能够经过接口声明被修饰的函数支持的调用方式:
interface Counter { (start: number): string; step: number; reset(): void; } function getCounter(): Counter { const counter = <Counter> function(start: number) {}; counter.step = 1; counter.reset = function() {}; } const c = getCounter(); c(1); c.reset(); c.step = 2;
面向对象中的类和接口内容实在是太多了,本文只选择了开发中经常使用到的用法进行说明,不足之处,敬请包涵。
对TS有兴趣的小伙伴能够扫码加我进行交流