函数类型
在javascript开发中,函数是重要的组成部门,并且可以作为一等公民(例如函数可以作为参数,也可以作为返回值进行传递等),在使用函数的过程中,可以编写函数类型的表达式来表示函数类型
export function useInterval(callback: () => void, delay: number | undefined, options?: { immediate?: boolean }): any {
const immediate = options?.immediate;
const fnRef = useLatest(callback);
const tick = useRef(undefined);
useEffect(() => {
// 如果有更变的话删除之前的定时器
clearInterval(tick.current?._id);
if (typeof delay !== 'number' || delay < 0) {
return;
}
if (immediate) {
fnRef.current();
}
tick.current = setInterval(() => {
fnRef.current();
}, delay);
return () => {
clearInterval(tick.current?._id);
};
// eslint-disable-next-line
}, [delay]);
}
上面的代码中,我实现了一个用于创建和管理一个定时器功能的函数
callback:定时器触发时要执行的回调函数.
delay number或undefined类型,定时器的时间间隔
if (typeof delay !== 'number' || delay < 0) { return; } 如果delay设置为undefined或小于0,定时器将不会启动.
options: 可选参数,包含一个可选的immediate属性
函数参数的类型
可选参数
函数不仅可以接受参数,而且可以指定某些参数是可选的,也拿上面的示例,options为可选参数,可以接收{}或undefined类型的数据,如果没有向options传递数据,那么options的值就为undefined
注意,在函数参数列表中,可选类型参数必须放在必选类型参数的后面.
默认参数
从es6开始,javascript和typescript都支持默认参数
function foo(x: number, y: number =20 ) {console.log(x, y)}
foo(30)
export {}
可以看到参数y有一个默认值20,因此y的类型实际上是undefined和number类型的联合
- 如果向y传入了值,则使用传入的值
- 如果向y传入undefined或没有传入值,则使用默认值20
注意:在函数参数中,参数的顺序应该是先写必传参数,然后写有默认值的参数,最后写可选参数.
剩余参数
从es6开始,javascript也开始支持剩余参数,剩余参数语法允许我们将不定数量的参数放到一个数组中
function sum(initalNum: number, ...nums: number[]): number{
let total: number = initalNum
for (const num of nums) { total += num }
return total
}
console.log(sum(1, 2, 3, 4))
可以看到...nums就是剩余参数,当调用sum函数时,除了第一个参数,其他的参数都会传递给nums
this的类型
javascript中的this是一个比较难理解的概念,简单来说,this表示当前函数的执行上下文,但是在不同的情况下,它所绑定的值是不同的
- 在一个对象中使用this时,它会绑定到该对象上
- 在全局环境中使用this时,它会绑定到全局对象上
class Code {
// success
static SUCCESS = 0
// 默认code
static FAILED = -1
// 当ErrorCode不存在ERROR_CODE_MAPPING常量,会报这个错误
static DEFAULT_ATTRIBUTE_CODE = -2
// 无效的SIGN参数
static INVALID_SIGN = -4
// 超时
static TIMEOUT = -5
// 为 Code 类添加一个索引签名
static [key: string]: number;
}
export class Message {
maps: { [key: number]: string | null } = {};
// 通用
SUCCESS = 'success!';
FAILED = '未知的code码,请检查响应代码';
INVALID_SIGN = '无效的标识';
TIMEOUT = '访问超时';
constructor() {
const keys = Object.keys(Code) as string[]; // 类型断言为 string[]
for (const key of keys) {
const code = (Code as any)[key]; // 使用类型断言绕过类型检查
if (this.hasOwnProperty(key)) {
this.maps[code] = (this as any)[key]; // 使用类型断言绕过类型检查
}else {
this.maps[code] = null;
}
}
}
}
const message = new Message();
console.log(message.maps);
这里我们在Message构造函数中使用this关键字引用了当前实例对象Message,并将Code的属性和Message实例属性的值存储到Message实例中maps属性对象里
函数重载
在编写javascript函数时,如果函数名称相同但参数的数量或类型不同,则被称其为函数重载
// 1.函数重载,使用联合类型实现
function add(a1: number | string, a2: number | string) {
if (typeof a1 === "number" && typeof a2 === "number") { // 类型缩小
return a1 + a2
}else if (typeof a1 === "string" && typeof a2 === "string"){
return a1 + a2
}
}
// 2.调用add函数,可以使字符串和数字类型相加
console.log(add(10 ,20))
console.log(add('coder', 'why'))
// 在typescript中,为了实现函数重载,还可以编写不同的重载签名表示函数可以以不同的方式进行调用
function sum(a1: number, a2: number): number
function sum(a1: string, a2: string): string
// 通用函数体
function sum (a1: any, a2: any): any {
return a1 + a2
}
// 调用sum函数,可以使字符串和数字类型相加
console.log(sum(20 , 30))
console.log(sum("coder", "why"))
export {}