视频地址 https://www.bilibili.com/video/av38379328/?p=3
1. 数据类型
- 定义未赋值,设置默认值
1 | let a:number | undefined; |
- 定义数组
1 | // 方式1 |
- 定义枚举
1 | enum flag {success: 1, error: 2} |
1 | enum Color {blue , red, 'orange'} |
如果标识没有赋值 则它的值就是下标
1 | enum Color {blue , red = 3, 'orange'} |
- 定义 void 类型,没有返回值
1 | function fun():void { |
- 定义
never
类型
包括 null
和 undefined
类型,是其他类型的子类型,代表从不会出现的值。
用 never
声明的变量只能用 never
类型的值所赋值。
1 | let a:never; |
2. 函数
- 可选参数
必须定义在参数最后一个
1 | function fun(name:string, age?:number){ |
- 剩余参数
三点运算符
1 | function fun(...res:number[]):number{ |
- 函数重载
1 | function fun(name:string){ |
1 | function fun(age:number){ |
这时候 fun
方法 就有2个参数,重载不会覆盖
3. 类
- 实例方法和静态方法
以 jquery 为例:
1 | // 静态方法 直接使用 |
ts 中静态方法:
1 | class Per { |
- 多态
父类定义一个方法不去实现,让继承它的子类去实现,每个子类有不同的表现。
1 | class A { |
- 抽象类
它提供其他类继承的基类,不能直接实例化。
用 abstract
关键字定义抽象类和抽象方法。
可以说抽象类和抽象方法使用来定义标准。
抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。
1 | // 抽象类必须有抽象方法 |
4. 接口
行为和动作的规范,对批量方法进行约束。
- 属性类型接口
1
2
3
4
5
6
7interface Name {
fName: string; // 必须
sName?: string; // 可选
}
function F(name:Name){
console.log(name.fName, name.sName)
} - 函数类型接口
1
2
3
4
5
6interface f{
(key: string, value: string): string
}
let md5:f = function(key: string, value: string): string{
return key + value
} - 可索引接口 (约束数组、对象)
1
2
3
4
5
6
7
8
9
10
11
12interface Arr {
[index: number]: string
}
let a: Arr = ["aa", "bb"]
interface Obj {
[index: string]: string
}
let o: Obj = {
aa: 'aaa',
bb: 'bbb'
} - 类类型接口
implements
实现后面的接口。
1 | interface C { |
- 接口拓展
接口继承其他接口。
1 | interface A { |
5. 泛型
简单理解:泛型就是解决类、接口和方法的复用性,以及对不特定数据类型的支持。
可以使用泛型来创建可重用的组件,一个组件支持多种类型的数据。
5.1 泛型函数
普通写法:
1
2
3
4
5
6
7
8
9
10// 只能返回一种类型
function fun1 (name: string): string{
return name;
}
// 可以返回多种类型
// 使用 any 则放弃使用类型检查
function fun2 (name: any): any {
return name;
}使用泛型:
由于如果使用 any
可能出现可以传入 string
返回 number
,所以需要使用泛型,使得传入参数和返回类型参数一致。
T
表示泛型,具体什么类型是调用这个方法的时候决定的。
1 | function fun3<T>(name: T): T{ |
5.2 泛型类
1 | class C<T>{ |
5.3 泛型接口
方法1:
1
2
3
4
5
6
7interface Config{
<T>(name: T): T;
}
let getData : Config = function<T>(name: T): T{ return name; }
getData<number>(123);
getData<string>('aaa');方法2:
1
2
3
4
5
6
7interface Config{
(name: T): T;
}
function getData<T>(name: T): T{ return name; }
let fun1: Config<string> = getData;
fun1('aaa')
5.4 把类作为参数类型的泛型类
- 以前将类作为参数类型,可以检查参数是否类型符合
1 | class User{ |
- 把类作为参数类型的泛型类
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Db<T>{
add(data: T): boolean{ return true }
}
class Data{
name: string | undefined;
pwd: string | undefined;
}
let dd = new Data();
dd.name = "aaa";
dd.pwd = "1233";
let D = new Db<Data>()
D.add(dd);
6. 模块
export
暴露模块, import
导入模块。
- 方式1
1 | // 1.js |
- 方式2
1 | // 1.js |
- 方式3 默认导出
1 | // 1.js |
7. 命名空间
在模块内部,用于组织代码,避免命名冲突。
使用 namespace
关键字作为划分,将指定的代码放到命名空间中,并使用 export
暴露其中变量和方法(类似将命名空间当做模块),调用的时候,需要使用 空间名称 来获取对应变量方法。
1 | namespace A{ |
8. 装饰器
是一种特殊类型的声明,能够被附加到类生命,方法,属性或参数上,可以修改类的行为。
常见:类装饰器,属性装饰器,方法装饰器,参数装饰器。
装饰器写法:普通装饰器(无法传参),装饰器工厂(可传参)
8.1 普通装饰器(无法传参)
1 | // 类装饰器 |
8.2 装饰器工厂(可传参)
1 | // 类装饰器 |
8.3 重载构造函数
用来修改当前类的构造函数,属性和方法。
1 | // 类装饰器 |
8.4 属性装饰器
1 | // 类装饰器 |
8.5 方法装饰器
用来监视、修改或替换方法的定义。
方法装饰会在运行时,传入三个参数:
- 对于静态方法来说是类的构造函数,对于实例方法是类的原型对象。
- 方法的名称。
- 方法的属性描述符。
1 | function logMethod(params: any){ |
8.6 方法参数装饰器
方法参数装饰器表达式会在运行时当做函数被调用,可以使用参数装饰器为类的原型添加一些元素数据。
方法装饰会在运行时,也是传入三个参数,和方法装饰器一样。
1 | function logMethod(params: any){ |
8.7 装饰器执行顺序
属性装饰器 - 方法装饰器 - 方法参数装饰器 - 类装饰器
多个相同类型装饰器,会从下开始执行,比如:
1 | @fun1('b') |
则先执行装饰器 fun2
再执行装饰器 fun1
。
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推荐 | https://github.com/pingan8787/Leo_Reading/issues |
JS小册 | js.pingan8787.com |
微信公众号 | 前端自习课 |