【前端,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)))

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/64778.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64778.shtml
英文地址,請注明出處:http://en.pswp.cn/web/64778.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

css的選擇器有哪些?優先級?

元素選擇器&#xff1a;選擇所有指定標簽類型的元素。 類選擇器&#xff1a;選擇具有指定類的所有元素&#xff0c;類名前有一個點 ID 選擇器&#xff1a;選擇具有指定 id 屬性的元素&#xff0c;ID 前有一個井號屬性選擇器&#xff1a;選擇具有指定屬性或屬性值的元素后代選…

Vue-Router之嵌套路由

在路由配置中&#xff0c;配置children import Vue from vue import VueRouter from vue-routerVue.use(VueRouter)const router new VueRouter({mode: history,base: import.meta.env.BASE_URL,routes: [{path: /,redirect: /home},{path: /home,name: home,component: () &…

Easy-Trans反向翻譯+Excel導入最佳實踐

1、概述 實現用戶excel上傳、解析、對于用戶輸入的中文翻譯為字典碼或者id&#xff0c;實現用戶輸入的參數校驗&#xff0c;最后入庫。如果用戶輸入的參數有問題&#xff0c;返回校驗結果給前端。 excel解析使用My-Excel組件&#xff0c;校驗使用hibernate-validator&#xff…

高效管理 Nginx 的利器:nginxWebUI 指南和 Docker 部署安裝過程

前言 Nginx WebUI 是一個為 Nginx 提供圖形化管理界面的工具。通過 WebUI&#xff0c;用戶可以輕松管理 Nginx 配置&#xff0c;而無需直接編輯配置文件&#xff0c;尤其適合新手用戶和頻繁修改配置的場景。 官網文檔&#xff1a;nginxWebUI - 文檔 本文將分享為什么選擇 ngin…

SpringCloud源碼-openFeign

LoadBalancer默認只有nacos服務發現器 openFeign與springcloud loadbalancer的結合點 openFeign通過spring cloud loadbalancer進行負載均衡&#xff0c;spring cloud loadbalancer通過discovery client獲取nacos的機器列表&#xff0c;然后底層進行負載均衡。

基于微信小程序的校園自助打印系統

博主介紹&#xff1a;java高級開發&#xff0c;從事互聯網行業六年&#xff0c;熟悉各種主流語言&#xff0c;精通java、python、php、爬蟲、web開發&#xff0c;已經做了多年的設計程序開發&#xff0c;開發過上千套設計程序&#xff0c;沒有什么華麗的語言&#xff0c;只有實…

從 ELK Stack 到簡單 — Elastic Cloud Serverless 上的 Elastic 可觀察性

作者&#xff1a;來自 Elastic Bahubali Shetti, Chris DiStasio 宣布 Elastic Cloud Serverless 上的 Elastic Observability 正式發布 — 一款完全托管的可觀察性解決方案。 隨著組織規模的擴大&#xff0c;一個能夠處理分布式云環境的復雜性并提供實時洞察的可觀察性解決方…

21.<基于Spring圖書管理系統②(圖書列表+刪除圖書+更改圖書)(非強制登錄版本完結)>

PS&#xff1a; 開閉原則 定義和背景 開閉原則&#xff08;Open-Closed Principle, OCP&#xff09;&#xff0c;也稱為開放封閉原則&#xff0c;是面向對象設計中的一個基本原則。該原則強調軟件中的模塊、類或函數應該對擴展開放&#xff0c;對修改封閉。這意味著一個軟件實體…

三、GIT與Github推送(上傳)和克隆(下載)

GIT與Github推送&#xff08;上傳&#xff09;和克隆&#xff08;下載&#xff09; 一、配置好SSH二、在Github創建倉庫三、git克隆&#xff08;下載&#xff09;文件四、git推送&#xff08;上傳&#xff09;文件到遠程倉庫 一、配置好SSH Git與Github上傳和下載時需要使用到…

網工日記:FTP兩種工作模式的區別

FTP 的主動模式和被動模式在連接建立的發起方、數據傳輸端口以及對網絡環境的適應性等方面存在明顯區別&#xff1a; 1. 連接發起方 主動模式&#xff1a;數據連接由服務器主動發起。在控制連接建立后&#xff0c;客戶端通過 PORT 命令告知服務器自己用于接收數據的臨時端口號…

【數字化】華為一體四面細化架構藍圖

導讀&#xff1a;華為的“一體四面”企業架構設計方法是一種綜合性的管理框架&#xff0c;它通過業務架構、信息架構、應用架構和技術架構的集成設計&#xff0c;構建出一個既符合業務需求&#xff0c;又具備高度靈活性和可擴展性的IT系統。這種架構設計方法強調從業務視角出發…

【linux板卡】lubancat通過vnc遠程訪問桌面

魯班貓開發板通過遠程VNC連接桌面&#xff1a; 硬件&#xff1a;lubancat2&#xff0c;網線 軟件&#xff1a;ssh軟件&#xff0c;vnc viewer 參考鏈接&#xff1a;https://training.eeworld.com.cn/video/38821 1、ssh連接lubancat2 &#xff0c;輸入ifconfig查看ip 2、輸入 …

解決Springboot整合Shiro+Redis退出登錄后不清除緩存

解決Springboot整合ShiroRedis退出登錄后不清除緩存 問題發現問題解決 問題發現 如果再使用緩存管理Shiro會話時&#xff0c;退出登錄后緩存的數據應該清空。 依賴文件如下&#xff1a; <dependency><groupId>org.springframework.boot</groupId><arti…

2024國城杯 Web

這四道題目Jasper大佬都做了鏡像可以直接拉取進行復現 https://jaspersec.top/2024/12/16/0x12%20%E5%9B%BD%E5%9F%8E%E6%9D%AF2024%20writeup%20with%20docker/ n0ob_un4er 這道題沒有復現成功, 不知道為啥上傳了文件, 也在 /tmp目錄下生成了sess_PHPSESSID的文件, 但是就是…

el-input輸入框需要支持多輸入,最后傳輸給后臺的字段值以逗號分割

需求&#xff1a;一個輸入框字段需要支持多次輸入&#xff0c;最后傳輸給后臺的字段值以逗號分割 解決方案&#xff1a;結合了el-tag組件的動態編輯標簽 那塊的代碼 //子組件 <template><div class"input-multiple-box" idinputMultipleBox><div>…

nginx 的 server 塊配置解析

前后端分離&#xff08;前端 flask&#xff09;&#xff1a; # 阻止ip訪問server {# default_server 是一個配置參數&#xff0c;用于指定當請求的域名&#xff08;Host 頭&#xff09;沒有匹配任何 server 塊時&#xff0c;Nginx 應該使用哪個 server 塊來處理這些請求。 lis…

Ubuntu 22.04.5 修改IP

Ubuntu22.04.5使用的是netplan管理網絡&#xff0c;因此需要在文件夾/etc/netplan下的01-network-manager-all.yaml中修改&#xff0c;需要權限&#xff0c;使用sudo vim或者其他編輯器&#xff0c;修改后的內容如下&#xff1a; # Let NetworkManager manage all devices on …

‘vue-cli-service‘ 不是內部或外部命令,也不是可運行的程序 或批處理文件。

這個錯誤信息表示系統找不到 vue-cli-service 命令&#xff0c;通常是因為 Vue 項目沒有正確安裝所需的依賴包。解決這個問題的步驟如下&#xff1a; 1. 確保你已經安裝了依賴 首先&#xff0c;確保你在項目目錄下&#xff0c;并且運行了以下命令來安裝項目所需的依賴&#x…

解決virtualbox克隆ubuntu虛擬機之后IP重復的問題

找遍了國內論壇&#xff0c;沒一個能解決該問題的&#xff0c;所以我自己寫個文章吧&#xff0c;真討厭那些只會搬運的&#xff0c;污染國內論壇環境&#xff0c;搜一個問題&#xff0c;千篇一律。 問題 操作系統版本為"Ubuntu 24.04 LTS" lennytest1:~$ cat /etc…

基于SpringBoot的寵物寄養系統的設計與實現(源碼+SQL+LW+部署講解)

文章目錄 摘 要1. 第1章 選題背景及研究意義1.1 選題背景1.2 研究意義1.3 論文結構安排 2. 第2章 相關開發技術2.1 前端技術2.2 后端技術2.3 數據庫技術 3. 第3章 可行性及需求分析3.1 可行性分析3.2 系統需求分析 4. 第4章 系統概要設計4.1 系統功能模塊設計4.2 數據庫設計 5.…