TypeScript 学习笔记(三):函数

news2024/11/22 11:07:38

一、函数定义

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

通常情况下,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.coloradmin.cn/o/744669.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【说明书】TA3001信号隔离器使用说明书

-为了方便需要的时候查阅分享说明书&#xff0c;特将其整理到CSDN。- 一、产品介绍&#xff1a; 给现场的变送器提供隔离电源&#xff0c;接收变送器输出的电流信号&#xff0c;隔离后输出给系统。该产品需要独立供电。 二、主要技术参数 1、供电电压:18~36 VDC 2、消耗电流…

python的字符串操作

1、字符串的驻留机制 字符串 在Python中字符串是基本数据类型&#xff0c;是一个不可变的字符序列什么叫字符串驻留机制呢? 仅保存一份相同且不可变字符串的方法&#xff0c;不同的值被存放在字符串的驻留池中&#xff0c;Python的驻留机制对相同的字符串只保留一份拷贝&…

想知道MLGO是如何工作的吗?看完这篇文章你就懂了

在当今软件开发领域&#xff0c;代码优化对于提高性能和减小代码体积至关重要。在这方面&#xff0c;内联&#xff08;Inlining&#xff09;被认为是一项关键的优化技术之一。而MLGO能够在编译过程中智能地做出内联/非内联的决策&#xff0c;从而提供更高效、更紧凑的代码。本文…

apk应用完整性校验

测试客户端程序是否对自身完整性进行校验。攻击者能够通过反编译的方法在客户端 程序中植入自己的木马&#xff0c;客户端程序如果没有自校验机制的话&#xff0c;攻击者可能会通过篡改客 户端程序窃取手机用户的隐私信息。 用 ApkTool 将目标 APK 文件解包&#xff0c;命令如…

linux下实现串口功能

1.先从wiringpi库复制一个串口代码 2.查看串口类型 3.将代码修改成ttyS5 4.改完代码后打开串口助手然后编译 代码示例&#xff1a; #include <stdio.h> #include <string.h> #include <errno.h> #include <pthread.h> #include <wiringPi.h> #i…

Ubuntu18.04.6本地部署PaddleSpeech实验代码(CPU版)

前言 因为本人不是搞python和AI的&#xff0c;所以部署这个项目是耗时耗力&#xff0c;本地部署还是挺麻烦的&#xff0c;发现了很多问题&#xff0c;关键就是权限和源代码路径问题&#xff0c;经历了14天&#xff08;大部分时间扔在做系统&#xff0c;装环境&#xff0c;代码阅…

【数学建模】常微分方程

常微分方程 博客园解释 https://www.cnblogs.com/docnan/p/8126460.html https://www.cnblogs.com/hanxi/archive/2011/12/02/2272597.html https://www.cnblogs.com/b0ttle/p/ODEaid.html matlab求解常微分方程 https://www.cnblogs.com/xxfx/p/12460628.html https://www.cn…

使用FreeMarker生成word文件自定义每页页眉或页脚

最新工作中遇到生成word中表格时&#xff0c;要求文档中每页头部和底部都是固定格式的表格&#xff0c;但是内容不一样&#xff0c;头部信息在word中画样式的时候就可以设置为“在各页顶端以标题形式重复出现”&#xff0c;而底部就没有办法这样设置了&#xff0c;之后就想着在…

【GPT模型】遥感云大数据在灾害、水体与湿地领域中的应用

近年来遥感技术得到了突飞猛进的发展&#xff0c;航天、航空、临近空间等多遥感平台不断增加&#xff0c;数据的空间、时间、光谱分辨率不断提高&#xff0c;数据量猛增&#xff0c;遥感数据已经越来越具有大数据特征。遥感大数据的出现为相关研究提供了前所未有的机遇&#xf…

TypeScript 中【class类】与 【 接口 Interfaces】的联合使用解读

导读&#xff1a; 前面章节&#xff0c;我们讲到过 接口&#xff08;Interface&#xff09;可以用于对「对象的形状&#xff08;Shape&#xff09;」进行描述。 本章节主要介绍接口的另一个用途&#xff0c;对类的一部分行为进行抽象。 类配合实现接口 实现&#xff08;impleme…

为什么Mate X3手机屏幕有水也不影响操作?

我知道现在的手机大多都防水&#xff0c;但没想到连折叠屏手机Mate X3在湿水状态下都丝毫不影响操作&#xff0c;现在的华为手机防水都做到这种程度了&#xff1f; 众所周知&#xff0c;如果手机屏幕上有水珠&#xff0c;那么手机的触屏就会变得飘忽不定。 这种“飘忽不定”是…

局域网聊天软件都有哪些?几款常用的局域网聊天软件推荐

随着科技的不断发展&#xff0c;人们在日常生活和工作中越来越需要高效便捷的沟通工具。而局域网聊天软件就是一种在局域网内使用的聊天工具&#xff0c;它能够帮助用户在同一网络内的设备之间进行即时通讯&#xff0c;无需依赖于互联网连接&#xff0c;安全又可靠。下面将为大…

学无止境·MySQL⑥(数据库备份和还原)

数据库备份和还原 备份和还原练习1、创建库和表2、使用mysqldump命令备份数据库中的所有表3、备份booksDB数据库中的books表4、使用mysqldump备份booksDB和test数据库5、使用mysqldump备份服务器中的所有数据库6、使用mysql命令还原第二题导出的book表7、进入数据库使用source命…

“快速批量去除文件夹名称中多余重复文字!轻松实现文件夹改名优化,提升整理效率!“

在日常的电脑使用中&#xff0c;我们常常面临着大量的文件和文件夹需要整理&#xff0c;而其中一个常见的问题就是文件夹名称中存在重复的文字&#xff0c;让整个文件夹结构变得混乱而不易管理。为了解决这一问题&#xff0c;我们自豪地推出了全新的文件夹改名工具&#xff0c;…

华为配置LLDP基本功能

华为配置LLDP基本功能 1.什么是lldp协议 定义 LLDP(Link Layer Discovery Protocol)是IEEE 802.1ab中定义的链路层发现协议。LLDP是一种标准的二层发现方式,可以将本端设备的管理地址、设备标识、接口标识等信息组织起来,并发布给自己的邻居设备,邻居设备收到这些信息后将…

产品新升级!MODBUS/SNMP智能协议转换器

“MODBUS TCP”是一种基于 TCP协议的工业控制设备通信协议&#xff0c;其主要功能是实现现场设备的远程控制。MODBUS TCP采用远程通讯的方式&#xff0c;通过 IP网络进行数据传输&#xff0c;因此其传输速率更快、网络负载更小、灵活性更高。 “ SNMP”是一种用于网络管理的…

如何考过PMP? 备考经历分享

考PMP的目的 周围很多同事、朋友都在学习PMP课程或者已获得证书&#xff0c;在日常工作中发现有些词语已经听不懂&#xff0c;比如项目集、项目组合&#xff0c;比如PM等&#xff0c;为了提升自己也为了能在侃大山时也能参与其中脱离“一清二白”的状态&#xff0c;所以下定决…

0基础学习云计算难吗?

很多人经常会问云计算是什么&#xff1f;云计算能干什么&#xff1f;学习云计算能做什么工作&#xff1f;其实我们有很多人并不知道云计算是什么&#xff0c;小知今天来给大家讲讲学习云计算能做什么。 中国的云计算行业目前正处于快速发展阶段&#xff0c;随着互联网和数字化…

SpringBoot 异常处理机制

SpringBoot中异常处理的流程图 在SpringBoot项目中&#xff0c;如果业务逻辑发生了异常&#xff0c;则首先看发生异常的类中有没有ExceptionHandle能处理&#xff0c;如果能&#xff0c;则执行方法进行处理&#xff0c;如果没有&#xff0c;则去找全局的ControllerAdvice注解…

X2000 Linux 调试VL53L4CD驱动

由于VL53L4CD具有更高的精度&#xff0c;更低的功耗&#xff0c;所以尝试将VL53L4CD移植到X2000上进行测试。 一、下载驱动 en.VL53L4CD_LinuxDriver 二、SDK中加入驱动 1、加入源码 在\module_driver\devices下创建VL53L4CD文件夹&#xff0c;再将\en.VL53L4CD_LinuxDriver…