当前位置: 首页 > news >正文

【前端,TypeScript】TypeScript速成(六):函数

函数

函数的定义

定义一个最简单的加法函数:

function add(a: number, b: number): number {return a + b
}

(可以看到 JavaScript/TypeScript 的语法与 Golang 也非常的相似)

调用该函数:

console.log(add(2, 3))
// out
[LOG]: 5

可选参数、默认参数和可变参数列表

在函数定义时,假定我们有一个可选的参数,可以在形参列表该参数后加上?。注意可选参数和默认参数一样都应该放在参数列表的后面:

function add(a: number, b: number, c?: number, d: number = 0): number {return a + b + (c || 0) + d
}console.log(add(2, 3))
console.log(add(2, 3, 9))
console.log(add(2, 3, 9, 15))
// out
[LOG]: 5 
[LOG]: 14 
[LOG]: 29

还可以加入一个可变参数列表:

function add(a: number, b: number, c?: number, d: number = 0,...e: number[]): number {let sum = a + b + (c || 0) + dfor(let i = 0; i < e.length; i ++) {sum += e[i]}return sum
}console.log(add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
// out
[LOG]: 55 

函数的重载

TypeScript 支持函数的重载(Golang 不允许函数的重载),但是不建议使用。

对象类型参数

假设我们现在有下述的函数定义:

function sendRequest(url: string, method: 'GET' | 'POST' | 'PUT',header: object,data: string,requireAuth: boolean,retry: boolean,retryTimeOut: number) {// ... ... ...
}

函数掉调用者在使用这个函数的时候,可能会给出非常冗长的参数列表,且我们无法从参数列表得知这个函数在做什么。

TypeScript 的一个解决办法是使用对象类型参数:

function sendRequest(params: {url: string, method: 'GET' | 'POST' | 'PUT',header: object,data: string,requireAuth: boolean,retry: boolean,retryTimeOut?: number,}) {// ... ... ...
}

参数直接是一个对象。函数调用时:

sendRequest({url: 'https://www.test.com',method: 'GET',header: {contentType: '... ... ...'},data: '{}',requireAuth: true,retry: true,retryTimeOut: 3000
})

这种做法使得函数调用者非常的方便。

通过函数为对象定义方法

将函数定义在对象内部,即可完成对象方法的定义:

const emp1 = {name: 'John',salary: 8000,performance : 3.5,bonus: undefined as (number | undefined),updataBonus() {if(!emp1.bonus) {emp1.bonus = emp1.salary * emp1.performance}},
}emp1.updataBonus()
console.log(emp1)// out
[LOG]: {"name": "John","salary": 8000,"performance": 3.5,"bonus": 28000
} 

观察对象方法的定义:

updataBonus() {if(!emp1.bonus) {emp1.bonus = emp1.salary * emp1.performance}
}

我们看到,必须通过 emp1 才能访问 bonus,但如果我们使用 emp2、emp3 来保存对象该怎么办呢?可以通过使用保留的关键字 this 来解决上述问题,修改后的方法如下:

updataBonus() {if(!this.bonus) {this.bonus = this.salary * this.performance}
}

函数式编程

函数式编程是 TypeScript/JavaScript 非常大的一个亮点,这个特性非常适配于前端开发。TypeScript/JavaScript 的 Promise 也是基于函数式编程的。

使用函数式编程辅助数组的排序

之前在对数组的学习过程当中我们提到过,直接对 number 类型的数组使用 sort 方法之后,数组将按照字典顺序排序,而不是按照数字大小的顺序排序。现在我们希望借助函数实现按照 number 大小进行排序:

function compareNumber(a: number, b: number) {// a < b -> 返回负数// a === b -> 返回 0// a > b -> 返回正数return a - b
}let a = [5, 2, 1, 6, 8, 10, 5, 25, 16, 23, 11]
a.sort(compareNumber)
console.log(a)

👆将函数名称传递给函数,就是函数式编程。(看起来和 C++ 当中的函数指针非常的像,但函数式编程比函数指针复杂很多,唯一和函数指针相似的地方就是在上述例子当中)

在函数式编程中,函数是一等公民

函数作为一等公民时:

  • 变量类型可以是函数;
  • 值(literal)可以是函数;
  • 对象的字段可以是函数;
  • 函数的参数也可以是函数;
  • 函数的返回值可以是函数。

变量类型可以是函数

上述的 compareNumber 函数的另一种定义形式如下:

const compareNumber = function(a: number, b: number) {return a - b
}

此时,compareNumber 是一个对象,它的类型是函数。

值(literal)可以是函数

上述 compareNumber 可以是一个变量,并被赋予其它的值(其它函数):

let compareNumber = function(a: number, b: number) {return a - b
}
compareNumber = function(a: number, b: number) {return b - a
}	// 实现降序排序

对象的字段也可以是函数

一个例子如下:

const emp1 = {name: 'John',salary: 8000,increaseSalary: function(p: number) {	// 此处不能使用箭头函数this.salary *= p					// 箭头函数和 this 之间有坑}
}

函数的参数可以是函数

比如 sort 的参数是 compareNumber。

函数的返回值可以是参数

一个例子如下:

function createComparer(greater: boolean = false) {return greater ? (a: number, b: number) => b - a : (a: number, b: number) => a - b
}let a = [5, 2, 1, 6, 8, 10, 5, 25, 16, 23, 11]
a.sort(createComparer())
console.log(a)

lambda 表达式

上述 compareNumber 函数更简单的写法如下:

let compareNumber = (a: number, b: number) => a - b

它是 lambda 表达式,在 TypeScript / JavaScript 中也被称为箭头函数。

一个快速实现排序的方法是:

a.sort((a: number, b: number) => a - b)

=>后面可以像函数体一样使用{ ... }包裹,但此时必须有返回值。

高阶函数

高阶函数指的就是返回值是函数的函数,这个概念类似于函数的叠加与嵌套。一个例子如下:

function loggingComparer(comp: (a: number, b: number) => number) {return (a: number, b: number) => {  // 对作为参数的函数进行包装console.log('comparing', a, b)  // 首先打印 logreturn comp(a, b)               // 再调用作为参数传入的函数}                                   // 看起来很像 Python 的 decorator
}

函数的闭包

在上述高阶函数 loggingComparer 的基础上,我们希望知道排序函数总共进行了多少次比较操作。可以通过函数的闭包(而不是设置全局变量)来实现上述功能。(使用全局变量的缺点在于全局变量或对象的状态字段需要维护,此外,打印同样改变了前端 UI 元素的状态,它同样也是一个副作用,我们应该尽可能地减少副作用,以提高用户体验)

一个函数闭包的例子如下,在下述代码片段中,函数 processArray 当中的局部函数 logger 和变量 compCount 是一个闭包,compCount 是它所携带的自由变量:

function loggingComparer(logger: (a: number, b: number) => void, comp: (a: number, b: number) => number) {return (a: number, b: number) => {  logger(a, b)  return comp(a, b)               }                                   
}function createComparer(params: {greater: boolean}) {return params.greater ? (a: number, b: number) => b - a : (a: number, b: number) => a - b
}let compareNumber = (a: number, b: number) => a - bfunction processArray(a: number[]) {let compCount = 0const logger = (a: number, b: number) => {console.log('comparing', a, b)compCount ++	}const comp = createComparer({greater: false})a.sort(loggingComparer(logger, comp))return compCount
}let a = [5, 2, 1, 6, 8, 10, 5, 25, 16, 23, 11]const compCount = processArray(a)
console.log(a)
console.log('Compare Count: ', compCount)

在上述例子中,随着 processArray 函数调用的结束,logger 函数也随之结束,compCount 作为返回值返回。但是如果 processArray 函数调用结束时,其内部的闭包由于某种原因尚未停止运行(比如一个线程),那么其所携带的自由变量的生命周期将会超越该函数的局部作用域。

部分应用函数

基于闭包可以实现部分应用函数。

一个部分应用的例子如下:

const a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(a.filter((v) => v % 2 == 0))
// out
[LOG]: [2, 4, 6, 8] 

一个等价的实现如下:

function isGoodNumber(goodFactor: number, v: number) {return v % goodFactor === 0
}function filterArray(a: number[], f: (v: number) => boolean) {return a.filter(f)
}const GOOD_FATOR = 2const a = [1, 2, 3, 4, 5, 6, 7, 8, 9]console.log(filterArray(a, (v) => isGoodNumber(GOOD_FATOR, v)))

相关文章:

【前端,TypeScript】TypeScript速成(六):函数

函数 函数的定义 定义一个最简单的加法函数&#xff1a; function add(a: number, b: number): number {return a b }&#xff08;可以看到 JavaScript/TypeScript 的语法与 Golang 也非常的相似&#xff09; 调用该函数&#xff1a; console.log(add(2, 3)) // out [LOG…...

React引入Echart水球图

在搭建React项目时候&#xff0c;遇到了Echart官方文档中没有的水球图&#xff0c;此时该如何配置并将它显示到项目中呢&#xff1f; 目录 一、拓展网站 二、安装 三、React中引入 1、在components文件夹下新建一个组件 2、在组件中引入 3、使用水波球组件 一、拓展网站 …...

谷歌浏览器的智能推荐功能使用指南

谷歌浏览器作为全球最受欢迎的网络浏览器之一&#xff0c;以其强大的功能和简洁的界面深受用户喜爱。其中&#xff0c;智能推荐功能通过利用先进的算法和数据分析&#xff0c;为用户提供个性化的内容推荐&#xff0c;大大提升了上网体验。本文将详细介绍如何开启和使用谷歌浏览…...

GitHub 上排名前 11 的开源管理后台(Admin Dashboard)项目

如果你是一名开发者&#xff0c;经常处理数据或参与项目管理&#xff0c;那么这篇文章绝对值得收藏&#xff01;当你需要一个高效、易用的管理后台&#xff08;Admin Dashboard&#xff09;项目时&#xff0c;本文会给你灵感。 在现代企业管理和业务运营中&#xff0c;管理后台…...

【运维】部署MKDocs

部署MKDocs obsidian 记录笔记&#xff0c;通过 mkdocs 私有化部署。 1 使用MKDocs创建笔记 创建仓库&#xff0c;安装 Material for MkDocs 和 mkdocs-minify-plugin mkdir tmp cd tmp git initpip install mkdocs-material pip install mkdocs-minify-pluginmkdocs new .2 …...

C# 读取多种CAN报文文件转换成统一格式数据,工具类:CanMsgRead

因为经常有读取CAN报文trace文件的需求&#xff0c;而且因为CAN卡不同、记录软件不同会导致CAN报文trace文件的格式都有差异。为了方便自己后续开发&#xff0c;我写了一个CanMsgRead工具类&#xff0c;只要提供CAN报文路径和CAN报文格式的选项即可将文件迅速读取转换为统一的C…...

计算机网络 (8)物理层的传输方式

一、串行传输与并行传输 串行传输 定义&#xff1a;串行传输是一种数据传输方式&#xff0c;指的是逐位地按照顺序传输数据。在串行传输中&#xff0c;数据位逐个按照一定的顺序进行传输&#xff0c;可以通过单条线路或信道进行。特点&#xff1a; 逐位传输&#xff1a;串行传输…...

【C#】WPF设置Separator为垂直方向

1. 方法1 <Separator BorderBrush"Gray"><Separator.LayoutTransform><RotateTransform Angle"90" /></Separator.LayoutTransform> </Separator>2. 方法2 <Separator Style"{StaticResource {x:Static ToolBar.S…...

太速科技-519-基于ZU19EG的4路100G光纤的PCIe 加速计算卡

基于ZU19EG的4路100G光纤的PCIe 加速计算卡 一、板卡概述 本板卡系我司自主设计研发&#xff0c;基于Xilinx公司Zynq UltraScale MPSOC系列SOC XCZU19EG-FFVC1760架构&#xff0c;支持PCIE Gen3x16模式。其中&#xff0c;ARM端搭载一组64-bit DDR4&#xff0c;总容量达…...

安卓入门二 Kotlin基础

Kotlin Kotlin的历史 Kotlin由Jet Brains公司开发设计&#xff0c;2011年公布第一版&#xff0c;2012年开源。 2016年发布1.0正式版&#xff0c;并且Jet Brains在IDEA加入对Kotlin的支持&#xff0c;安卓自此又有新的选择。 2019年谷歌宣布Kotlin成为安卓第一开发语言&#x…...

C++ ——— 单/多参数构造函数的隐式类型转换和 explicit 关键字

单参数构造函数 代码演示&#xff1a; class A { public:A(int i):_a(i){}private:int _a; }; 在 A 这个类中的构造函数只有一个参数&#xff0c;这就称之为单参数的构造函数 不同形式实例化对象 代码演示&#xff1a; A a1(1);A a2 2; a1 的实例化过程&#xff1a; 第…...

Java编程规约:集合处理

文章目录 I 集合处理【强制】【推荐】II 知识扩展I 集合处理 【强制】 不要在 foreach 循环里进行元素的 remove / add 操作。remove 元素请使用 iterator 方式,如果并发操作,需要对 iterator 对象加锁。// 正例: List<String> list = new ArrayList<>(...

IOS safari 播放 mp4 遇到的坎儿

起因 事情的起因是调试 IOS 手机下播放服务器接口返回的 mp4 文件流失败。对于没调试过移动端和 Safari 的我来说着实费了些功夫&#xff0c;网上和AI也没有讲明白。好在最终大概理清楚了&#xff0c;在这里整理出来供有缘人参考。 问题 因为直接用 IOS 手机的浏览器打开页面…...

plsql :用户system通过sysdba连接数据库--报错ora-01031

一、winR cmd通过命令窗口登录sys用户 sql sys/[password]//localhost:1521/[service_name] as sysdba二、输入用户名:sys as sysdba 三、输入密码:自己设的 四、执行grant sysdba to system; 再去PL/SQL连接就可以了...

LabVIEW条件配置对话框

条件配置对话框&#xff08;Configure Condition Dialog Box&#xff09; 要求&#xff1a;Base Development System 当右键单击**条件禁用结构&#xff08;Conditional Disable Structure&#xff09;**并选择以下选项时&#xff0c;会显示此对话框&#xff1a; Add Subdiagr…...

PyAudio库基本知识详解——为自制PCM音频播放器做准备

前言 结合前段时间我们做的音频编解码器&#xff0c;这样我们就可以将获取到的ADPCM数据&#xff0c;转换成PCM数据&#xff0c;然后播放出来&#xff0c;得到一个完整的音频数据&#xff0c;因此&#xff0c;接下来几篇文章中&#xff0c;我们想做一个播放PCM格式的音频播放器…...

Git如何添加子仓库

背景 项目中经常使用别人维护的模块&#xff0c;在git中使用子模块的功能能够大大提高开发效率。 使用子模块后&#xff0c;不必负责子模块的维护&#xff0c;只需要在必要的时候同步更新子模块即可。 本文主要讲解子模块相关的基础命令&#xff0c;详细使用请参考main page…...

001__VMware软件和ubuntu系统安装(镜像)

[ 基本难度系数 ]:★☆☆☆☆ 一、Vmware软件和Ubuntu系统说明&#xff1a; a、Vmware软件的说明&#xff1a; 官网&#xff1a; 历史版本&#xff1a; 如何下载&#xff1f; b、Ubuntu系统的说明&#xff1a; 4、linux系统的其他版本&#xff1a;红旗(redhat)、dibian、cent…...

在国产电脑上运行PDFSAM软件使用pdf分割合并交替混合处理pdf文档

软件下载地址: https://sourceforge.net/projects/pdfsam/files/ 需要注意事项&#xff0c;系统需要java环境&#xff0c;确认系统有java环境&#xff0c;根据软件版本需求安装对应的java运行环境。 下载pdfsam-4.3.4-linux.tar.gz安装包&#xff0c;解压&#xff0c;将runt…...

STM32完全学习——FATFS0.15移植SD卡

一、下载FATFS源码 大家都知道使用CubMAX可以很快的将&#xff0c;FATFS文件管理系统移植到单片机上&#xff0c;但是别的芯片没有这么好用的工具&#xff0c;就需要自己从官网下载源码进行移植。我们首先解决SD卡的驱动问题&#xff0c;然后再移植FATFS文件管理系统。 二、SD…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...