一、介绍
函数是JavaScript程序的基础,函数可以实现抽象层、模拟类、信息隐藏和模块。虽然typescript中已经支持了类、命名空间和模块,但是函数仍然是主要的定位行为的地方。typescript增强了函数的功能,使得函数可以更易于使用
二、函数类型
typescript中,函数也是一种类型,其形式可以描述如下:
(参数名1: 类型, 参数名2: 类型) => 返回类型
如以下这个函数:
let add = function(x: number, y: number): number {
return x + y
}
它的类型会被自动推断为:
(x: number, y: number) => number
一般使用中,我们可以不必完整写出函数类型
,因为typescript会为我们自动推断出类型,需要注意的是:类型中的参数名称可以不必和值中的参数名称匹配,只要它们类型是兼容的便可:
let add: (x: number, y: number) => number
add = function(a: number, b: number): number {
return x + y
}
三、可选参数与默认参数
typescript里每个函数参数都是必须的,这和JavaScript有点不同,即:
function buildName(firstName: string, lastName: string) {
return firstName + ' ' + lastName
}
let n1 = buildName('Ruphi') // 报错,缺少第二个参数
let n2 = buildName('Ruphi', 'Lau', ' ') // 报错,传入了额外的参数
let n3 = buildName('Ruphi', 'Lau') // 允许
而JavaScript里,每个参数都是可选的,可传可不传,那么typescript能够实现这样子吗?当然可以,答案是使用可选参数
,参数名后面接一个?
,该参数便成为了可选参数,需要注意:
可选参数
必须跟在必须参数
后面
例子如:
function buildName(firstName: string, lastName?: string) {
return firstName + (lastName ? ' ' + lastName : '')
}
let n1 = buildName('Ruphi') // 允许
let n2 = buildName('Ruphi', 'Lau', '') // 报错,传入了额外的参数
let n3 = buildName('Ruphi', 'Lau') // 允许
当用户没有给一个参数传递值或者传递的值是undefined
时,这个参数叫做可以有默认值的参数,我们可以使用=
指定这种情况下的取值,如:
function buildName(firstName: string, lastName = 'Lau') {
return firstName + ' ' + lastName
}
let n1 = buildName('Ruphi') // 允许,返回'Ruphi Lau'
let n2 = buildName('Ruphi', undefined) // 允许,返回'Ruphi Lau'
在所有的必须参数后接的带默认值
的参数都是可选的,与可选参数一样,在调用函数的时候是可以省略的,但是有默认值
的参数不一定要放在必须参数
的后面,也可以放在前面,当传入undefined
的时候,就会取默认参数指定的默认值
四、剩余参数
与ES6一样,typescript也支持剩余参数,示例如:
function max(...args: number[]): number {
return Math.max(...args)
}
五、this问题
typescript中,可以在第一个参数里指定this
的类型,如:
class User {
constructor(public name: string, public age: number) {
}
show(this: User, doing: string) {
console.log(`${this.name} is ${this.age}, now is ${doing}`)
}
}
let p = new User('Ruphi', 21)
p.show('Coding')
可以发现,虽然this
在方法第一个参数的位置,但是它的作用实际上只是限定this
的类型,并不是让我们作为第一个参数传值
回调函数里的this
可以对回调函数里的this
类型做限定,如:
interface UIElement {
addClickListener(onclick: (this: void, e: Event) => void): void
}
其中,this: void
表示addClickListener
期望onclick
回调函数不需要指定this
的类型。那么限定了this
类型后,会有什么效果呢?看如下例子:
class Handler {
info: string
onClickBad(this: Handler, e: Event) {
this.info = e.message
}
}
const h = new Handler()
uiElement.addClickListener(h.onClickBad) // 报错,因为this类型不匹配
// 修复报错:变更this类型
class Handler {
info: string
onClickBad(this: void, e: Event) {
this.info = e.message
}
}
const h = new Handler()
uiElement.addClickListener(h.onClickBad)
六、重载
typescript允许我们定义多个函数类型定义
来进行函数重载,编译器会根据定义列表去处理函数的调用,如:
function foo(x: number): string
function foo(x: string): string
function foo(x): any {
if (typeof x === 'number') {
return `${x} is a number`
} else if (typeof x === 'string') {
return `${x} is a string`
}
}
console.log(foo(123)) // 输出:123 is a number
console.log(foo('123')) // 输出:'123' is a string