- 函数,一个再熟悉不过的话题了,之前几章里面我们也多次提到过,而且提到过各种各样的 TS 内和函数相关的内容
- 今天,咱们来详细说一下函数内的各种详细内容的使用
文章目录
- 一、函数的可选参数
- 二、函数内的虚拟 this
- 三、函数的重载
一、函数的可选参数
- 在 TS 中,是可以给函数的参数添加类型限制的,先来看一个例子
function fn(a: number, b: number): void {}
- 这就是一个很简单的函数
- 我们使用的时候,只要给两个 number 类型的数据作为参数即可
- 现在呢,我有一个想法,就是我使用这个函数的时候,第二个参数可不可以不填
- 小伙伴: “这还不简单吗,给形参来一个默认值”
function fn(a: number, b: number = 0): void {}
- 完成任务了,好简单
- 但是我要说的不是这个,而是当你的逻辑内需要判断用户是不是没有传递参数的时候
- 咱们来看下面两个需求
- 需求1: 如果确实传递了两个参数,那么我按照两个参数去计算结果,如果第二个没有传递,我给个默认值,还是按照两餐参数去计算结果
// 比如,我们的随机数函数
function fn(a: number = 10, b: number = 0): number {return Math.floor(Math.random() * (Math.abs(a - b +1))) + Math.min()
}
- 你传了参数,我就用你传的,你没有传递的时候,那么我就用我自己设定的默认值就好了
- 需求2: 如果传递了两个参数,我执行两个参数的逻辑,如果第二个参数没有传递,那么我就按照一个参数来执行逻辑
// 比如,我们设置 cookie 的时候的一个简单的操作
function fn(a: string, b: string, c: number): void {let timeif (c) { time = new Date()time.setTime(time.getTime() - 1000 * 60 * 60 * 8 + 1000 * c)}document.cookie = `${ a }=${ b };expires=${ c }`
}
- 你传递了参数 c,那么我就用,你没有传递 c,那么我就不用就好了
- 以上两段逻辑明显不一样
- 其实,说了这么多,我就是想告诉你们一个事情
- 那就是函数的参数可以设置选填
function fn(a: number, b?: number): void {}
- 只要在书写形参的时候,在形参后面加上一个 问号(?) 就可以了
- 就像我们在对象接口内书写选填成员一样
- 这样,这个参数就可以不传递了,也不会报错
- 注意
- 必选参数不可以放在选填参数的后面
- 选填参数不允许设置默认值了
二、函数内的虚拟 this
- 这里我们说的可不是函数内的 this 指向谁,而是如何对函数内的 this 进行类型限制
- 小伙伴: " 什么,this 还需要限制吗 ? "
- 当然了,既然是类型限制,那么我们一个也不要放过了
- 先来看一个函数
function fn() {console.log(this.innerHTML)
}
- 这是一个非常简单的函数
- 如果我们把它当做某一个元素的事件处理函数,是完全没有问题的
- 但是这里的 this 并没有做出任何限制,那么在使用的时候会不会出现问题呢 ?
- TS 一定会考虑这个问题,所以会给你提示一个错误
- 所以在 TS 的配置文件内,有一个配置
{"noImplicitThis": true, // false}
- 默认值是 true,表示在你的项目内不允许出现没有类型限制的 this
- 选填是 false,表示不管你的 this 是什么,ts 都不管了
- 所以这是一个解决方案
- 但是很显然,这并不友好,我们最好还是给 this 加上一个限制
- 在这里,我们就可以在书写函数的时候,在参数的第一个位置,加上一个 this 的限制
function fn(this: HTMLDivElement) {console.log(this.innerHTML)
}
- 这里的 this 并不是该函数的第一个参数,而是一个虚拟参数,只是限定了该函数内的 this 数据类型
- 既然在这里已经做出了限制,那么函数内在使用的时候就不会提示错了
- 但是也说了,这个函数在调用的时候,必须要让函数内 this 为 HTMLDivElement 类型
function fn(this: HTMLDivElement) {console.log(this.innerHTML)
}// box 是获取到得以一个 div 元素
box.onclick = fn
- 这样就可以,完全没有问题的
function fn(this: HTMLDivElement) {console.log(this.innerHTML)
}
fn()
- 这样就会提示错误了
- 因为要求函数内的 this 必须是 HTMLDivElement 类型
- 但是如果你直接调用 fn 函数的话,内部的 this 并不是 HTMLDivElement 类型
- 就会提示错误了
- 注意: 我们一定要分清,这个 this 限定并不是函数的第一个参数
三、函数的重载
- 啥也不说了,先看一个例子吧
- 有一个简单的函数,实现字符串反转操作
function fn(x: string): string {return x.split('').reverse().join('')
}
- 在来一个函数,实现一个数字放大 100 倍的操作
function fn(x: number): number {return x * 100
}
- 因为某些原因,我必须要要讲两个函数合并为一个函数
function fn(x: string | number): string | number {// 需要在函数内进行条件判断if (typeof x === 'number') {return x * 100} else {return x.split('').reverse().join('')}
}
- 上面这个函数,看起来没有任何问题,我们也可以正常使用
- 但是,我发现使用完毕以后出现了问题
- 惊不惊喜,意不意外,这是为什么 ?
- 根据这个函数,我们来看
- 参数限定 : 可以是 string 也可以是 number
- 返回值限定 : 可以是 string 也可以是 number
- 看似没有问题,但是呢 …
- 它并没有限制什么参数对应什么返回值
- 比如,我们如果参数是 string,那么返回值可以是 string 或者 number
- 比如,我们如果参数是 number,那么返回值也可以是 string 或者 number
- 并不是我们一开始想要的
- 参数是 string 返回值也是 string
- 参数是 number 返回值也是 number
- 那么当我们调用的时候,不管你传递的是什么参数
- ts 都会认为,返回值是 string 或者 number 类型
- 当你用返回值调用 toFixed 的时候
- ts 就会认为,你有可能是一个 string 类型,那么 string 类型是没有 toFixed 这个方法的,所以就会提示错误
- 也就是说,你这样写完
- 如果你再也不用返回值了,那么没啥事
- 但是如果你要用返回值去调用一些方法,那么只能调用两种数据类型共有的方法
- 那我该怎么办 ?
- 这个时候,就可以用到 函数的重载 了
- 其实就是在定义函数之前,把这个函数我需要的几种情况列举出来
// 情况1:
function fn(x: string): string
// 情况2:
function fn(x: number): number
function fn(x: string | number): string | number {if (typeof x === 'number') {return x * 100} else {return x.split('').reverse().join('')}
}
- 函数还是这个函数
- 但是在这个函数之前,我们列举了两种情况
- 参数是 string,返回值也是 string
- 参数是 number,返回值也是 number
- 今后在调用的时候, 就只会出现这两种情况了
- 这样就不会报错了