愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

Typescript学习记录:函数

一、介绍

函数是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 = 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的类型,并不是让我们作为第一个参数传值


六、重载

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