函数类型
命名函数
命名函数是使用关键字
function
编写的函数声明,在当前范围内以不同名称提供。 在运行任何代码之前,命名函数声明会加载到执行上下文中。 此过程称为提升,这意味着你可以在声明函数之前使用该函数。
//命名函数
function addNumbers(x: number, y: number): number {
return x + y;
}
console.log(addNumbers(1, 2)); // 返回值是number类型
匿名函数
函数表达式(或匿名函数)是未预先加载到执行上下文中的函数,并且仅当代码遇到该函数时才会运行。 函数表达式是在运行时创建的,并且必须先声明才能调用。 不会对它们进行提升,而命名函数声明在程序开始执行时就会进行提升,并且可以在其声明之前调用。
函数表达式表示值,因此通常会将这些值分配给变量或传递给其他函数,这意味着函数没有名称。
//匿名函数
let addNumbers = function (x: number, y: number): number {
return x + y;
}
console.log(addNumbers(1, 2)); // 返回值是number类型
//示例2
let sum = function (input: number[]): number {
let total: number = 0;
// 遍历数组,计算总和
for(let i = 0; i < input.length; i++) {
// 如果元素不是数字,则跳过
if(isNaN(input[i])) {
continue;
}
// 将元素转换为数字,并累加
total += Number(input[i]);
}
// 返回总和
return total;
}
console.log(sum([1, 2, 3]));
// 在此示例中,变量 sum 不是类型化的变量,但 TypeScript 可以通过称为“上下文类型化”的内容(一种类型推理形式)来确定其类型。 确定上下文类型可以减少保持程序类型所需的工作量。
箭头函数
箭头函数(也称为 Lambda 或胖箭头函数,因为定义它们的是
=>
运算符)提供用于定义匿名函数的简写语法。 由于其简洁性,箭头函数通常用于简单的函数和某些事件处理场景。
// 匿名函数
let addNumbers1 = function (x: number, y: number): number {
return x + y;
}
// 箭头函数
// 单行箭头函数可以使用简洁体文语法,也可以使用隐式返回,这允许省略大括号和 return 关键字。
let addNumbers2 = (x: number, y: number): number => x + y;
// 如果函数体有多行,则用大括号括起来,并包含 return 语句(如适用)。
let total2 = (input: number[]): number => {
// 定义一个变量total,用于存储总和
let total: number = 0;
// 遍历input数组,如果元素是数字,则将其转换为数字类型,并累加到total中
for(let i = 0; i < input.length; i++) {
if(isNaN(input[i])) {
continue;
}
total += Number(input[i]);
}
// 返回total
return total;
}
箭头函数是在 ES2015 中引入的,因此并非所有浏览器都支持它们。 通过使用 TypeScript,你可以利用这些函数类型,然后转译到更低的 JavaScript 版本(如有必要),这样你的代码就可以在旧版浏览器上使用。
函数的参数
TypeScript 编译器假定在函数中定义的所有参数都是必需的。调用函数时,TypeScript 编译器将验证:
已为每个参数提供值。 仅将函数所需的参数传递给它。 按在函数中定义的顺序传递参数。 这些要求不同于 JavaScript。 JavaScript 假定所有形参都是可选的,你可以向函数传递比函数定义的更多(或更少)的实参。
必须的参数
函数的参数都是必须的
数量和类型必须匹配
可选参数
还可以通过在参数名后面附加问号 (?) 来定义可选参数。
//可选参数
function addNumbers (x: number, y?: number): number {
if (y === undefined) {
return x;
} else {
return x + y;
}
}
addNumbers(1, 2); // 输出3
addNumbers(1); // 输出1
默认参数
还可以为可选参数分配默认值。 如果将值作为实参传递给可选形参,则将向其分配该值。 否则,将为它分配默认值。 与可选参数一样,默认参数必须位于参数列表中所需的参数之后。
// 默认参数
function addNumbers (x: number, y = 25): number {
return x + y;
}
addNumbers(1, 2); // 输出 3
addNumbers(1); // 输出 26
如果在 y 之后又加了个参数 z: number 则中间的默认参数不可缺省。
rest 参数
如果要将多个参数作为一个组(例如,在数组中传递它们)。 或者,如果你不知道函数最终将采用多少个参数。 可以使用 rest 参数。 rest 参数被视为无限数量的可选参数。 可以将它们保留不动,或根据需要调整数量。
// 定义一个函数,接收第一个数字和剩余数字的数组,返回总和
let addAllNumbers = (firstNumber: number, ...restOfNumbers: number[]): number => {
// 定义一个变量,用于存储总和
let total: number = firstNumber;
// 遍历剩余数字的数组
for(let counter = 0; counter < restOfNumbers.length; counter++) {
// 如果当前数字不是数字,则跳过
if(isNaN(restOfNumbers[counter])){
continue;
}
// 将当前数字转换为数字类型,并累加到总和中
total += Number(restOfNumbers[counter]);
}
// 返回总和
return total;
}
addAllNumbers(1, 2, 3, 4, 5, 6, 7); // 输出 28
addAllNumbers(2); // 输出 2
console.log(addAllNumbers(2, 3, "three")); //输出5 编译提示:类型“string”的参数不能赋给类型“number”的参数。
析构对象参数
函数参数是有位置的,必须按照它们在函数中定义的顺序传递。 在调用具有多个可选参数或相同数据类型的函数时,位置参数可能会降低代码的可读性。
若要启用命名参数,可以使用“析构对象参数”技术。 此项技术使你能够在函数中使用接口来定义命名参数,而不是位置参数。
// 定义一个消息接口,接口包含文本和发送者
interface Message {
text: string;
sender: string;
}
// 定义一个显示消息的函数,函数接收一个消息对象,消息对象包含文本和发送者
function displayMessage({text, sender}: Message) {
console.log(`Message from ${sender}: ${text}`);
}
displayMessage({sender: 'Christopher', text: 'hello, world'});
定义函数类型
自定义函数类型
可以定义函数类型,然后在创建函数时使用它们。 如果要对多个函数应用相同的函数类型签名,此设计会很有用
可以使用类型别名或接口来定义函数类型。 这两种方法本质上都是相同的,因此由你决定哪种方法最适合。 如果希望选择扩展函数类型,接口是更好的选择。 如果要使用联合或元组,则类型别名更好。
// 函数别名定义函数类型
// 使用类型别名定义名为 calculator 的函数类型。 类型签名有一个参数列表 (x: number, y: number) 并返回 number,以箭头 (=>) 运算符分隔。
type calculator = (x: number, y: number) => number;
// 现在可以在声明函数时使用函数类型作为类型签名。 声明函数类型 calculator 的两个变量,一个用于加法运算,一个用于减法运算。 通过将每个函数的结果返回到控制台来测试新函数。
let addNumbers:calculator=(x:number,y:number):number=> x+y;
let subtractNumbers:calculator=(x:number,y:number):number=> x-y;
console.log(addNumbers(1, 2));
console.log(subtractNumbers(1, 2));
//使用接口 声明函数类型
interface Calculator {
(x: number, y: number): number;
}
// 就 TypeScript 而言,这三个语句是相同的
let addNumbers: Calculator = (x: number, y: number): number => x + y;
let addNumbers: Calculator = (number1: number, number2: number): number => number1 + number2;
let addNumbers: Calculator = (num1, num2) => num1 + num2;
函数类型推理
编译器检查函数类型是否兼容是=时,忽略参数名。
TypeScript 将依据函数类型定义(参数类型和返回类型) 推断出输入的形参类型。
所以 上面接口中定义的 addNumbers 都是一样的。
知识检查
-
TypeScript 中的函数参数与 JavaScript 中的函数参数之间的区别是什么?
默认情况下,TypeScript 参数是必需的,但可以是可选的。 JavaScript 参数始终是可选的。
2. 匿名函数的常见用途是什么?
需要为变量指定函数表达式时。(匿名函数通常用于将函数表达式分配给变量,或将函数传递给另一个函数。)
3. 如果需要扩展函数类型,应如何定义它?
使用接口定义它。(使用接口而不使用类型别名的一个原因是可以扩展接口,而类型别名则不能。)
原文始发于微信公众号(王大可996):TypeScript学习笔记(8)-函数
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/205221.html