TypeScript 学习笔记(三):函数

一、函数定义

函数是由一连串的子程序(语句的集合)所组成的,可以被外部程序调用,向函数传递参数之后,函数可以返回一定的值。

通常情况下,TypeScript 代码是自上而下执行的,不过函数体内部的代码则不是这样。如果只是对函数进行了声明,其中的代码并不会执行,只有在调用函数时才会执行函数体内部的代码。

二、函数格式类型

1. 函数定义类型:

function add(arg1: number, arg2: number): number {return x + y;
}
// 或者
const add = (arg1: number, arg2: number): number => {return x + y;
};

上面例子中参数 arg1 和 arg2 都是数值类型,最后通过相加得到的结果也是数值类型。

如果在这里省略参数的类型,TypeScript 会默认这个参数是 any 类型;如果省略返回值的类型,如果函数无返回值,那么 TypeScript 会默认函数返回值是 void 类型;如果函数有返回值,那么 TypeScript 会根据我们定义的逻辑推断出返回类型。

2. 完整的函数类型

一个函数的定义包括函数名、参数、逻辑和返回值。我们为一个函数定义类型时,完整的定义应该包括参数类型和返回值类型。上面的例子中,我们都是在定义函数的指定参数类型和返回值类型。接下来我们看下,如何定义一个完整的函数类型,以及用这个函数类型来规定一个函数定义时参数和返回值需要符合的类型。先来看例子然后再进行解释:

let add: (x: number, y: number) => number;
add = (arg1: number, arg2: number): number => arg1 + arg2;
add = (arg1: string, arg2: string): string => arg1 + arg2; // error

上面这个例子中,我们首先定义了一个变量 add,给它指定了函数类型,也就是(x: number, y: number) => number,这个函数类型包含参数和返回值的类型。然后我们给 add 赋了一个实际的函数,这个函数参数类型和返回类型都和函数类型中定义的一致,所以可以赋值。后面我们又给它赋了一个新函数,而这个函数的参数类型和返回值类型都是 string 类型,这时就会报如下错误:
在这里插入图片描述
函数中如果使用了函数体之外定义的变量,这个变量的类型是不体现在函数类型定义的。

3. 使用接口定义函数类型

interface Add {(x: number, y: number): number;
}
let add: Add = (arg1: string, arg2: string): string => arg1 + arg2; // error 不能将类型“(arg1: string, arg2: string) => string”分配给类型“Add”

在这里插入图片描述

4. 使用类型别名

type Add = (x: number, y: number) => number;
let add: Add = (arg1: string, arg2: string): string => arg1 + arg2; // error 不能将类型“(arg1: string, arg2: string) => string”分配给类型“Add”

使用type关键字可以为原始值、联合类型、元组以及任何我们定义的类型起一个别名。上面定义了 Add 这个别名后,Add就成为了一个和(x: number, y: number) => number一致的类型定义。例子中定义了Add类型,指定add类型为Add,但是给add赋的值并不满足Add类型要求,所以报错。

三、参数

1. 必选参数

必选参数:在调用函数的时候,必须要传入的参数,参数列表里边的参数默认就是必选参数,只要在声明的时候写了参数,在传递的时候,就必须传入参数,而且,实参与形参的数量与类型要一致。

type Add = (x: number, y: number) => number;
let add: Add = (arg1: string, arg2: string): string => arg1 + arg2;add(1, 2); // right
add(1, 2, 3); // error 应有 2 个参数,但获得 3 个
add(1); // error 应有 2 个参数,但获得 1 个

2. 可选参数

可选参数:为了解决在函数传参的时候,某些参数可以不用传递,我们就需要可选参数了

function getInfo(name: string, age?: number): string {return `${name} --- ${age}`;
}console.log(getInfo("张三", 28)); // 正确
console.log(getInfo("张三")); // 正确
console.log(getInfo(28)); // 错误
type Add = (x?: number, y: number) => number; // error 必选参数不能位于可选参数后。

注意:可选参数必须配置到参数的最后面。

3. 默认参数

默认参数:为了解决在函数传参的时候,某些参数可以不用传递,但是我们又需要该参数的值,这时候我们就需要给这个参数设定一个默认值也叫初始化值,就得用到默认参数了。

function getInfo(name: string, age: number = 20): string {return `${name} --- ${age}`;
}console.log(getInfo("张三", 28)); // 正确
console.log(getInfo("张三")); // 正确
console.log(getInfo(28)); // 错误

注意:可选参数不能够进行初始化值的设定。

4. 剩余参数

剩余参数:在参数的类型确定而参数个数不确定的情况时,我们需要用到剩余参数,它使用 … 将接收到的参数传到一个指定类型的数组中。

function sum(...result: number[]): number {let sum = 0;for (let i = 0; i < result.length; i++) {sum += result[i];}return sum;
}console.log(sum(1, 2, 3, 4, 5, 6));
function sum(init: number, ...result: number[]): number {let sum = init;for (let i = 0; i < result.length; i++) {sum += result[i];}return sum;
}console.log(sum(100, 1, 2, 3, 4, 5, 6));

注意:剩余参数必须配置到参数的最后面。

四、函数重载

1. 函数签名

函数签名主要定义了参数及参数类型,返回值及返回值类型。函数签名不同,函数会做出不同的处理。

2. 构造器重载

举个例子,声明一个类Course,里面写一个begin的方法,我们调用 begin时传入不同参数类型已经参数个数,begin方法会做出不同处理,那么怎么实现呢?4个重载签名和1个实现签名具体如下:

type Combinable = number | string;
class Course {//定义重载签名begin(name: number, score: number): string;begin(name: string, score: string): string;begin(name: string, score: number): string;begin(name: number, score: string): string;//定义实现签名begin(name: Combinable, score: Combinable) {if (typeof name === 'string' || typeof score === 'string') {return 'student:' + name + ':' + score; }}
}const course = new Course();
console.log(course.begin(111, 5)); //没有输出
console.log(course.begin('zhangsan', 5)); //student:zhangsan:5
console.log(course.begin(5, 'zhangsan')); //student:5:zhangsan

3. 联合类型函数重载

声明一个函数uniteFunctionOverloading,参数类型为联合类型,返回值也是联合类型,但是如下代码却报错了。

function uniteFunctionOverloading(x: number | string): number | string {if (typeof x === 'number') {return x;} else {return x+'是字符串';}
}
uniteFunctionOverloading(1).toFixed(1); // 报错 类型“string | number”上不存在属性“toFixed”。类型“string”上不存在属性“toFixed”

我们可以可以根据传参的类型和函数返回值声明多个同名的函数,只是类型和返回值不同而已。

function uniteFunctionOverloading(x: number): number;
function uniteFunctionOverloading(x: string): string; 
function uniteFunctionOverloading(x: number | string): number | string {if (typeof x === 'number') {return x;} else {return x+'是字符串';}
}
uniteFunctionOverloading(1).toFixed(1);

这样就不会报错了,可以利用重载将多种情况声明这样就可推导类型更细致,因为已经识别到uniteFunctionOverloading(1)的返回值是number类型。

五、拓展JS中函数重载

1. 利用arguments参数

var arr = [1,2,3,4,5];
//注意:这里不能写成箭头函数,否则this指向的是window对象
Array.prototype.search = function() {var len = arguments.length;switch(len){case 0:return this;case 1:return `${arguments[0]}`;case 2:return `${arguments[0]},${arguments[1]}`;}
}
console.log(arr.search()) //[1,2,3,4,5]
console.log(arr.search(1)) //1
console.log(arr.search(1,2)) //1,2

2. 利用闭包和arguments

 function addMethod (obj, name, fn) {var old = obj[name];obj[name] = function () {if (fn.length === arguments.length) {return fn.apply(this, arguments)} else if (typeof old === 'function') {return old.apply(this, arguments)}}}var person = {name: 'zhangsan'}addMethod(person, 'getName', function () {console.log(this.name + '---->' + 'getName1')})addMethod(person, 'getName', function (str) {console.log(this.name + '---->' + str)})addMethod(person, 'getName', function (a, b) {console.log(this.name + '---->' + (a + b))})person.getName()  person.getName('zhangsan')person.getName(10, 20)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/19954.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PicGo搭建Gitee图床

文章目录 1、创建Gitee仓库2. 填写仓库信息3、生成私人令牌3.1、点击个人设置3.2、点击私人令牌3.3、生成新令牌3.4、密码验证3.5、记录个人令牌 4、PicGo配置4.1、插件设置&#xff0c;安装gitee插件4.2、PicGo图床配置为gitee并设置详细信息 5、特殊问题5.1、上传失败原因15.…

电商API接口商品页面数据(详情数据,销量数据,sku数据,视频数据,优惠券数据)接口代码示例

有探讨稳定采集电商等多平台整站实时商品详情历史价格数据接口&#xff0c;通过该接口开发者可以更好地了解商品的情况&#xff0c;商品详情数据详细信息查询&#xff0c;数据参数包括&#xff1a;商品链接&#xff0c;商品列表主图、价格、标题&#xff0c;sku&#xff0c;库存…

Hystrix 断路器

文章目录 1 问题&#xff1a;服务雪崩2 概念3 服务降级3.1 概念&#xff1a;3.2 触发服务降级的情况&#xff1a;3.3 应用3.3.1 依赖3.3.2 解决的问题3.3.3 生产者&#xff1a;3.3.4 消费者&#xff1a;3.3.5 配置全局fallback方法3.3.6 解耦合 4 服务熔断4.1 概念&#xff1a;…

面试题大杂烩-记不住

1、分库分表图啥 分库是为了解决单库io连接数的瓶颈 分表是为了解决单表效率瓶颈 2、分表后如何limit分页 如果是根据xxx字段进行分表的话 那么shardingjdbc会根据字段进行笛卡尔积计算 去对应表里面执行sql到内存中计算&#xff0c;比如根据用户id进行hash算法进行查表&…

Win10下安装TensorRT

Win10下安装TensorRT 前言相关介绍Win10下安装TensorRT查看cuda版本下载tensorrt8.xx版本&#xff0c;适用于Windows的cuda11.x的版本解压下载好的压缩包使用pip下载wheel文件遇到新问题解决方法 测试TensorRT是否安装成功 参考 前言 由于本人水平有限&#xff0c;难免出现错漏…

C++STL:顺序容器之forward_list

文章目录 1. 概述2. 成员函数和使用forward_list容器相关的函数 3. forward_list 容器的创建 1. 概述 forward_list 是 C 11 新添加的一类容器&#xff0c;其底层实现和 list 容器一样&#xff0c;采用的也是链表结构&#xff0c;只不过 forward_list 使用的是单链表&#xff…

【MySQL】SQL索引失效的几种场景及优化

MySQL中提高性能的一个最有效的方式是对数据表设计合理的索引。索引提供了高效访问数据的方法&#xff0c;并且加快查询的速度&#xff0c; 因此索引对查询的速度有着至关重要的影响。 使用索引可以快速地定位表中的某条记录&#xff0c;从而提高数据库查询的速度&#xff0c;…

软件工程——第13章软件项目管理知识点整理(完结)

本专栏是博主个人笔记&#xff0c;主要目的是利用碎片化的时间来记忆软工知识点&#xff0c;特此声明&#xff01; 文章目录 1.管理的定义&#xff1f; 2.软件项目管理地位&#xff1f;&#xff08;重要性&#xff09; 3.软件项目管理过程从一组项目计划活动开始&#xff0c…

raid5故障导致LeftHand存储崩溃的服务器数据恢复案例

HP-LeftHand存储简介&#xff1a; HP LeftHand存储支持RAID5、RAID6、RAID10磁盘阵列&#xff0c;支持卷快照&#xff0c;卷动态扩容等。 服务端&#xff1a; 客户端&#xff1a; LeftHand存储分为三个层级&#xff1a;物理磁盘、逻辑磁盘、逻辑卷。多个物理磁盘组成一个逻辑的…

GPDB-内核特性-gp_interconnect_fc_method参数

GPDB-内核特性-gp_interconnect_fc_method参数 gp_interconnect_fc_method参数控制使用哪种流量控制方式&#xff1a;capacity根据接收方窗口来控制发送&#xff1b;loss(默认)根据丢包情况控制发送速度。Loss是基于capacity&#xff0c;还会根据丢包情况调整发送速度。那么针对…

YOLOv8实战垃圾分类目标检测 (视频课程)

课程链接&#xff1a;https://edu.csdn.net/course/detail/38804 垃圾分类是一项利国利民的民生工程&#xff0c;需要全社会的共同参与。 YOLOv8是前沿的目标检测技术&#xff0c;它基于先前 YOLO 版本在目标检测任务上的成功&#xff0c;进一步提升性能和灵活性。 本课程将手…

基于OpenCV 和 Python 实现车牌检测--附免费源码

文末提供免费的源代码下载链接 车牌检测是使用计算机视觉技术自动检测和识别图像或视频流中的车牌/车牌的过程。 此任务在许多应用中都很有用,例如交通管理、自动收费和停车控制。 车牌检测基本上分为两个任务: 车牌检测:这是指识别图像或视频帧中车牌位置的过程。这涉…