TypeScript学习笔记(8)-函数

函数类型

命名函数

命名函数是使用关键字  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 都是一样的。

知识检查

  1. TypeScript 中的函数参数与 JavaScript 中的函数参数之间的区别是什么?

默认情况下,TypeScript 参数是必需的,但可以是可选的。 JavaScript 参数始终是可选的。

2.  匿名函数的常见用途是什么?
         需要为变量指定函数表达式时。(匿名函数通常用于将函数表达式分配给变量,或将函数传递给另一个函数。)

3.  如果需要扩展函数类型,应如何定义它?
         使用接口定义它。(使用接口而不使用类型别名的一个原因是可以扩展接口,而类型别名则不能。)



原文始发于微信公众号(王大可996):TypeScript学习笔记(8)-函数

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/205221.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!