TypeScript新手入门学习指南,持续更新中~

这篇博客是TypeScript新手入门的学习指南,详细介绍了类、对象、面向对象的三大特性和更多高级特性,如枚举、常量枚举、泛型等,通过实例深入浅出地解释了TypeScript的用法。

let str = 123

function getLength2(input: string | number): number{

if(typeof input === ‘string’){

return input.length

}else{

return input.toString().length

}

}

[](()五、Typescript中的类:class

================================================================================

js 中我们用了构造函数和原型链的方式来实现继承,同时在 ES6 中出现了 class 类继承的方法。那在 typescript 中呢,继承的方法又更加丰富了。让我们一起来一探究竟吧!

[](()1、类的定义


我们先来看下类的定义。

[](()(1)类(Class)

类定义了一切事物的抽象特点,包含它的属性和方法。比如:

class Animal{

// 构造函数是实例化执行时候的逻辑

constructor(name){

this.name = name

}

run(){

return ${this.name} is running

}

}

阅读以上代码我们可以知道,通过 class 可以定义一个

[](()(2)对象(Object)

对象 Object ,就是类的实例举个例子: 🙆‍♂️

我们可以把类 class 比喻成一张蓝图,比如说汽车是一个 class ,那么它就像是一张造汽车的图纸。第二个是 ObjectObject 通过 new 生成,那么前面有了汽车的蓝图,我们现在就可以创造实实在在的汽车了。我们可以说一辆特斯拉是汽车的实例,也可以说宝马是汽车的另外一个实例。

同样我们用上面的例子来做衍生。具体如下:

class Animal{

// 构造函数是实例化执行时候的逻辑

constructor(name){

this.name = name

}

run(){

return ${this.name} is running

}

}

const snake = new Animal(‘lily’)

console.log(snake.run())

阅读以上代码我们可以知道,我们定义了一个 snake ,这个 snake 继承了 Animal 类,因此它就可以用 Animal 类的属性方法

此时打印结果如下:

实例

[](()(3)面向对象(OOP)的三大特性

面向对象的三大特性分别为:封装继承多态

  • 封装: 指将数据的操作细节隐藏起来,只暴露对外的接口。那这样子的话,对于外界的调用端来说,他们不需要也不可能知道细节,只能通过对外的接口来访问该对象。

  • 继承: 子类可以继承父类,子类除了拥有父类的所有特征外,还会拥有一些更具体的特性

  • 多态: 由继承产生的相关不同的类,对同一个方法可以有不同的响应。比如,猫和狗,他们都可以继承 Animal 类,但是他们分别实现 run() 方法,此时呢,针对某一个实例,我们无需了解它是猫还是狗,这个时候可以直接调用 run() ,程序会自动判断出来,应该如何去执行这个方法。

同样,我们用上面的代码做衍生,来看继承多态是怎么样的。


继承:

class Animal{

// 构造函数是实例化执行时候的逻辑

constructor(name){

this.name = name

}

run(){

return ${this.name} is running

}

}

const snake = new Animal(‘lily’)

// console.log(snake.run())

class Dog extends Animal{

bark(){

return ${this.name} is barking

}

}

const xiaoqi = new Dog(‘xiaoqi’)

console.log(xiaoqi.run())

console.log(xiaoqi.bark())

此时打印结果如下:

继承

从上面可以看到, Dog 继承了 Animal 类,此时 Dog 就拥有了 Animal 类的属性和方法。而 xiaoqi 实例化了 Dog ,因此它也拥有 Dog 的属性和方法。


多态:

class Animal{

// 构造函数是实例化执行时候的逻辑

constructor(name){

this.name = name

}

run(){

return ${this.name} is running

}

}

const snake = new Animal(‘lily’)

// console.log(snake.run())

//-----------------------------------

class Dog extends Animal{

bark(){

return ${this.name} is barking

}

}

const xiaoqi = new Dog(‘xiaoqi’)

console.log(xiaoqi.run())

console.log(xiaoqi.bark())

//-----------------------------------

class Cat extends Animal{

// 静态方法不需要进行实例化,直接在类上调用即可

static categories = [‘mammal’]

constructor(name){

super(name)

console.log(this.name)

}

run(){

return Meow, + super.run()

}

}

const maomao = new Cat(‘maomao’)

console.log(maomao.run())

// 直接访问静态属性

// 为什么要有静态属性?当定义和实例没有太大关系时,可以考虑使用静态方法实现

console.log(Cat.categories)

此时打印结果如下:

多态

阅读代码我们可以发现, xiaoqi 继承了 dogrun() 方法,而 Cat 继承了 Animal 类,但是它对 run() 方法进行了改写,因此最终的 run() 方法为改写后的效果。

所以, maomao 继承了 Cat 类,最后 maomao 调用 run() 方法时,就会调用 Cat 里面改写的 run() 方法,而不是 Animal 类的 run() 方法。

这样, xiaoqimaomao 虽然同样继承自 Animal 类,但他们调用 run() 方法的结果各自相互独立,如此,就实现了多态。

同时,我们还要注意一个点,就是静态属性。大家可以看到上面定义的 categories ,用了 static 来定义它为静态属性。当把变量定义为静态属性时,则当外部需要该静态方法时,不需要进行实例化,之类在类上调用即可。

那么问题来了,我们什么时候才需要有静态属性呢?

其实,当定义的内容和实例没有太大关系时,就可以考虑使用静态方法。比如常量的使用,常量基本是固定的,不会变的,所以我们可以考虑直接使用静态方法来获取它。

[](()2、Typescript中的类


Typescript是通过什么方式来增强类的呢,typescript一般通过以下四种修饰符来增强类:

| 修饰符 | 含义 |

| :-: | :-: |

| public | 修饰的属性或方法是公有的 |

| private | 修饰的属性或方法是私有的 |

| protected | 修饰的属性或方法是受保护的 |

| readonly | 只能读不能写 |

有了以上这四种修饰符呢,我们就可以给类的方法和属性进行权限管理。为什么要做权限管理呢?因为总有些内容,我们是不愿意暴露给外部使用的,所以需要进行权限管理。

值得注意的是,对于 protected 这个修饰符来说,只有子类可以访问父类的属性和方法其他实例都不能访问。这其实可以把 protected 这个变量理解为遗产,父类的东西直接给子女继承,其余外部人员一概不能访问。

[](()3、类和接口


[](()(1)解决什么问题

继承存在着这样一个困境,在面向对象的世界中,一个类只能继承另外一个类,有时候同类之间有一些共同的特性,但是使用子类来继承父类又很难完成。于是接口就出现了。

[](()(2)如何解决

类可以使用 implements 来实现接口,怎么做呢?我们可以把这些相同的特性提取成接口,然后用 implements 这个关键字来实现,这样就大大提高了面向对象的灵活性。

[](()(3)举个例子

假如我们现在要让一辆汽车和一部手机来实现打开播放器的功能那么我们会这么实现:

class Car{

switchRadio(trigger: boolean){

}

}

class CellPhone{

switchRadio(trigger: boolean){

}

}

但是这样子看起来好像就没有特别雅观。于是我们可以写一个打开播放器的接口,然后用 implements 来实现这个功能。代码如下:

interface Radio{

switchRadio(trigger: boolean): void

}

class Car implements Radio{

switchRadio(trigger: boolean){

}

}

class CellPhone implements Radio{

switchRadio(trigger: boolean){

}

}

这样,就让Car和CellPhone实现了打开播放器的功能。

接下来,我们继续写一个接口,可以实现检查电池电量的功能。并且让手机不仅可以打开播放器,还可以检查电池电量。代码如下:

interface Radio{

switchRadio(trigger: boolean): void

}

interface Battery{

checkBatteryStatus(): void

}

class Car implements Radio{

switchRadio(trigger: boolean){

}

}

class CellPhone implements Radio,Battery{

switchRadio(trigger: boolean){

}

checkBatteryStatus(){

}

}

阅读代码我们可以发现,我们要给继承两个接口 Radio,Battery ,这样看似乎还有点冗余。于是我们可以这样实现:

interface Radio{

switchRadio(trigger: boolean): void

}

interface RadioWithBattery extends Radio{

checkBatteryStatus(): void

}

class Car implements Radio{

switchRadio(trigger: boolean){

}

}

class CellPhone implements RadioWithBattery{

switchRadio(trigger: boolean){

}

checkBatteryStatus(){

}

}

通过 interface 继承 interface ,最终用 implement 去抽象和验证类的属性和方法,达到抽离功能的目的。

相信通过以上的简单了解,大家能感受到一点 interface 的奇妙之处。

[](()六、枚举

===============================================================

[](()1、普通枚举

---------- 《大厂前端面试题解析+Web核心总结学习笔记+企业项目实战源码+最新高清讲解视频》无偿开源 徽信搜索公众号【编程进阶路】 -------------------------------------------------------

枚举常使用于我们在程序中需要做权限管理或者做判断时等各种场景。枚举比较简单,下面直接用代码演示:

enum Direction{

Up,

Down,

Left,

Right

}

console.log(Direction.Up) //0

console.log(Direction.Down) //1

console.log(Direction.Left) //2

console.log(Direction.Right) //3

console.log(Direction[0]) //Up

除了以上基本用法外,我们还可以给枚举赋值:

enum Direction{

Up = 10,

Down,

Left,

Right

}

console.log(Direction.Up) //10

[](()2、常量枚举


我们来定义一个常量,与 enum 做判断。

enum Direction{

Up = ‘Up’,

Down = ‘Down’,

Left = ‘Left’,

Right = ‘Right’

}

//定义一个常量,直接与enum做判断

const value = ‘Up’;

if(value === Direction.Up){

console.log(‘go Up!’) // go Up!

}

使用常量枚举可以有效地提升性能,常量会内联枚举的任何用法,而不会把枚举变成任意的 Javascript 代码。

这样一说,那是不是所有的 enum 都可以使用常量枚举呢?答案自然是否定的。

枚举的值有两种类型,一种是常量值枚举(constant),一种是计算值枚举(computed)。只有常量值枚举可以进行常量枚举,而计算值枚举不能进行常量枚举

本文持续更新中~

如果大家不想等待连载文章的话,我整理了一份1.8W字TypeScript入门指南,附大量代码实例,需要的朋友[点击此处就可免费领取。](()

[](()一、TypeScript 是什么


1.1 TypeScript 与 JavaScript 的区别

1.2 获取 TypeScript

1.3 典型 TypeScript 工作流程

1.4 TypeScript 初体验

[](()二、TypeScript 基础类型


2.1 Boolean 类型

2.2 Number 类型

2.3 String 类型

2.4 Symbol 类型

2.5 Array 类型

2.6 Enum 类型

2.7 Any 类型

2.8 Unknown 类型

2.9 Tuple 类型

2.10 Void 类型

2.11 Null 和 Undefined 类型

2.12 object, Object 和 {} 类型

2.13 Never 类型

[](()三、TypeScript 断言


3.1 类型断言

3.2 非空断言

3.3 确定赋值断言

[](()四、类型守卫


4.1 in 关键字

4.2 typeof 关键字

4.3 instanceof 关键字

4.4 自定义类型保护的类型谓词

[](()五、联合类型和类型别名


5.1 联合类型

5.2 可辨识联合

5.3 类型别名

[](()六、交叉类型


6.1 同名基础类型属性的合并

6.2 同名非基础类型属性的合并

[](()七、TypeScript 函数


7.1 TypeScript 函数与 JavaScript 函数的区别

7.2 箭头函数

7.3 参数类型和返回类型

7.4 函数类型

7.5 可选参数及默认参数

7.6 剩余参数

7.7 函数重载

[](()八、TypeScript 数组


8.1 数组解构

8.2 数组展开运算符

8.3 数组遍历

[](()九、TypeScript 对象


9.1 对象解构

9.2 对象展开运算符

[](()十、TypeScript 接口


10.1 对象的形状

10.2 可选 | 只读属性

10.3 任意属性

10.4 接口与类型别名的区别

[](()十一、TypeScript 类


11.1 类的属性与方法

11.2 ECMAScript 私有字段

11.3 访问器

11.4 类的继承

11.5 抽象类

11.6 类方法重载

[](()十二、TypeScript 泛型


12.1 泛型语法

12.2 泛型接口

12.3 泛型类

12.4 泛型工具类型

[](()十三、TypeScript 装饰器


13.1 装饰器是什么

13.2 装饰器的分类

13.3 类装饰器

13.4 属性装饰器

13.5 方法装饰器

13.6 参数装饰器

[](()十四、TypeScript 4.0 新特性


14.1 构造函数的类属性推断

14.2 标记的元组元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值