函数是 JavaScript 应用程序的基础, 它可以实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义行为的地方,TypeScript 为JavaScript 函数添加了额外的功能,更容易地使用。
和JavaScript一样,TypeScript函数可以创建有名字的函数和匿名函数。 可以随意选择适合应用程序的方式,不论是定义一系列API函数还是只使用一次的函数。
function add1(x: number, y: number): number { return x + y;
} let add2 = function (x: number, y: number): number { return x + y; };
完整函数类型
let sub1: (x:number, y:number) => number = function(a: number, b: number): number { return x-y; };
函数类型包含两部分:参数类型和返回值类型。 当写出完整函数类型的时候,这两部分都是需要的。 只要参数类型是匹配的,那么就认为它是有效的函数类型,而不在乎参数名是否正确。对于返回值, 在函数和返回值类型之前使用( =>)符号,使之清晰明了。返回值类型是函数类型的必要部分,如果函数没有返回任何值,你也必须指定返回值类型为 void 而不能留空。
推断类型
let sub2 = function(a: number, b: number): number { return a - b; };
如果在赋值语句的一边指定了类型但是另一边没有类型的话,TypeScript编译器会自动识别出类型。
TypeScript里的每个函数参数都是必须的。 这不是指不能传递 null或undefined作为参数,而是说编译器检查用户是否为每个参数都传入了值。 编译器还会假设只有这些参数会被传递进函数。 简短地说,传递给一个函数的参数个数必须与函数期望的参数个数一致。
在TypeScript里我们可以在参数名旁使用 ? 实现可选参数的功能。
function buildName1(firstName: string, lastName?: string) { if (lastName) return firstName + " " + lastName; else return firstName;
} console.log(buildName1("Bob")); // 输出:Bob // console.log(buildName1("Bob", "Adams", "Sr.")); // Error console.log(buildName1("Bob", "Adams")); // 输出:Bob Adams
可选参数必须跟在必须参数后面。
在TypeScript里,可以为参数提供一个默认值当用户没有传递这个参数或传递的值是 undefined 时,它们叫做有默认初始化值的参数。
function buildName2(firstName: string, lastName = "Smith") {
return firstName + " " + lastName;
}
console.log(buildName2("Bob")); // 输出:Bob Smith
console.log(buildName2("Bob", undefined)); // 输出:Bob Smith
// console.log(buildName2("Bob", "Adams", "Sr.")); // Error
console.log(buildName2("Bob", "Adams")); // 输出:Bob Adams
在所有必须参数后面的带默认初始化的参数都是可选的,与可选参数一样,在调用函数的时候可以省略。 也就是说可选参数与末尾的默认参数共享参数类型。
与普通可选参数不同的是,带默认值的参数不需要放在必须参数的后面。 如果带默认值的参数出现在必须参数前面,用户必须明确的传入 undefined值来获得默认值。
必要参数,默认参数和可选参数有个共同点:它们表示某一个参数。 如果同时操作多个参数,或者并不知道会有多少参数传递进来。 在JavaScript里,可以使用 arguments 来访问所有传入的参数。
在 TypeScript 里,可以把所有参数收集到一个变量里:
function buildName3(firstName: string, ...restOfName: string[]) { return firstName + " " + restOfName.join(" ");
} console.log(buildName3("Joseph", "Samuel", "Lucas", "MacKinzie")); // 输出:Joseph Joseph Lucas Lucas
剩余参数会被当做个数不限的可选参数。 可以一个都没有,同样也可以有任意个。 编译器创建参数数组,名字是在省略号( …)后面给定的名字,可以在函数体内使用这个数组。这个省略号( …)也会在带有剩余参数的函数类型定义上使用到。
箭头函数(lambda表达式)是 ES6 在语法上提供的一个很好的特性。
var array = [1, 2, 3];
array.forEach(v => console.log(v)); // 输出: 1 2 3
普通 function 函数和箭头函数的行为有区别,箭头函数没有它自己的 this 值,箭头函数内的 this 值继承自外围作用域。
var array = [1, 2, 3];
array.forEach(v => console.log(v)); // 输出: 1 2 3 class Handler {
message: string;
change = (m: string) => { this.message = m };
output = () => { console.log(this.message) };
} let handler = new Handler();
handler.change("Hello");
handler.output();
JavaScript 本身是个动态语言,JavaScript 里函数根据传入不同的参数而返回不同类型的数据是很常见的。可以为同一个函数提供多个函数类型定义来进行函数重载, 编译器会根据这个列表去处理函数的调用。
class FooClass {
public bar(s: string): number;
public bar(n: number): string;
public bar(arg: string | number): any { if (typeof arg === 'number') return arg.toString(); if (typeof arg === 'string') return arg.length;
}
}
为了让编译器能够选择正确的检查类型,它与JavaScript里的处理流程相似。 它查找重载列表,尝试使用第一个重载定义。 如果匹配的话就使用这个。 因此,在定义重载的时候,一定要把最精确的定义放在最前面。