如何在TypeScript中使用函數(shù)
前言
雖然 JS/TS 支持面向?qū)ο缶幊蹋蟛糠謺r候還是在寫函數(shù)。函數(shù)是一等公民。本文介紹下如何在 TypeScript 中使用函數(shù),包括:
- 函數(shù)類型聲明
- 函數(shù)參數(shù)類型:可選參數(shù)、默認參數(shù)、剩余參數(shù)
- 函數(shù)返回值類型
- this 類型
- 函數(shù)重載
函數(shù)類型
面試中經(jīng)常會被問到,JS 中有哪幾種數(shù)據(jù)類型。其中就會有函數(shù)類型。
JS 中的函數(shù)類型很模糊,準確來說,僅有類型的概念,卻無類型的實質(zhì)。好在有了 TS 強類型的加持,現(xiàn)在可以好好定義一個函數(shù)的類型了。
聲明一個函數(shù)類型,有若干種不同的方式。比如通過 interface 定義函數(shù)類型,通過 type 聲明函數(shù)類型別名,在類聲明中聲明函數(shù)類型等等。
但核心就一點,只關(guān)注函數(shù)參數(shù)的類型和返回值的類型。
下面就從函數(shù)的聲明入手,來看看函數(shù)類型的使用。
函數(shù)的聲明方式
有三種最簡單的函數(shù)聲明方式。
使用 function
關(guān)鍵字進行聲明:
function add(a: number, b: number): number { return a + b }
通過函數(shù)表達式進行聲明:
let add = function (a: number, b: number): number { return a + b }
或者使用箭頭函數(shù):
let add = (a: number, b: number): number => { return a + b }
上面這三種聲明函數(shù)的方式和 JS 中聲明函數(shù)別無二致,就是多了兩點:
- 函數(shù)參數(shù)需要給明類型
- 函數(shù)返回值也需要給出類型
那么函數(shù)類型到底在哪里呢?把鼠標移動到函數(shù)名字上就能看到了:
和聲明普通變量變量一樣:
let name = 'kunwu'
如果沒有使用類型注解,那么編譯器會自動推導(dǎo)出類型來。上面紅框標識出來的類型,就是編譯器推導(dǎo)出來的。
函數(shù)的類型注解
函數(shù)的類型形如 (參數(shù):類型) => 類型,所以函數(shù)的類型注解就是:
let add: (a: number, b: number) => number = function (a, b) { return a + b }
通常函數(shù)的類型都比較長,此時可以使用 type 類型別名,來聲明一個標識符表示該類型:
type Add = (a: number, b: number) => number let add: Add => number = function (a, b) { return a + b }
這樣,聲明函數(shù)類型,使用函數(shù)類型,看上去就很簡潔直觀了。
對象中的函數(shù)類型
函數(shù)的參數(shù)
聲明函數(shù)時,可以使用類型注解聲明參數(shù)類型。如果不指定類型,默認類型是 any
。
function add (a: number, b: number) :number { return a + b }
可選參數(shù)
可選參數(shù)使用 ?
標記,需要放到固定參數(shù)的后面:
const fn = (a: number, b?:number) => { if(b) { return a + b } else { return a } }
可選參數(shù)意味著參數(shù)可傳可不傳。通過編譯器的類型推導(dǎo),可以看到好像可選參數(shù)等同于一個聯(lián)合類型:
但其實并不等同。
可選參數(shù)表示參數(shù)可傳可不傳,若傳則必須是指定的類型。
而直接將參數(shù)類型聲明為 string|undefined
,意味著這是個必傳參數(shù),必須傳實參。
參數(shù)默認值
參數(shù)的默認值,在參數(shù)的類型后面使用 =
聲明:
const fn = (a: number, b: number = 10): number => { return a + b }
剩余參數(shù)
剩余參數(shù)是 ES6 中的一個特性,使用剩余運算符 ...
來獲取函數(shù)實參中未被形參聲明的變量,其取得的值是一個數(shù)組,比如:
function add(a,b, ...args) { console.log(args) } add(1,2,3,4,5)
則剩余參數(shù) args 就等于 [3, 4, 5]。
TS 中剩余參數(shù)也要有類型聲明,需要將其聲明為數(shù)組類型或者元組類型。
function add(a: number, b: number, ...args: number[]) { console.log(c) }
剩余參數(shù)和其他的固定參數(shù)不同。其他的固定參數(shù)聲明了類型,則必須傳該類型的值。而剩余參數(shù)雖然也聲明了類型,但可傳可不傳,可傳一個,可傳多個,比如:
function add(a: number, b: number, ...args: number[]) { console.log(args) } add(1, 2) // [ ] add(1, 2, 3) // [ 3 ] add(1, 2, 3, 4) // [ 3, 4 ]
還可以將剩余參數(shù)類型聲明為元組類型,元組中還可以繼續(xù)使用可選參數(shù),在參數(shù)后使用 ?
表示:
function log( ...args: [string, number, boolean?]) { console.log(args) } log('Shinichi', 17) // [ 'Shinichi', 17 ] log('Zoro', 19, true) // [ 'Zoro', 19, true ]
函數(shù)的返回值類型
函數(shù)的返回值類型可以通過類型注解指定。如果不指定的話,TS 編譯器能夠根據(jù)函數(shù)體的 return 語句自動推斷出返回值類型,因此我們也可以省略返回值類型。
TS 基本類型中有一個 void 類型,表示空類型,它唯一的用處就是用作函數(shù)的返回值類型。當一個函數(shù)沒有 return 語句時,
如果函數(shù)使用 return 語句返回了 undefined 值,則返回值類型就為 undefined 而不是 void 了:
但是此時可以將返回值類型使用類型注解指定為 void:
this 類型
JS 函數(shù)中到處可見 this 的身影。關(guān)于 this 的指向也是前端八股中的基礎(chǔ)之基礎(chǔ)。
默認情況下 TS 編譯器會將函數(shù)中的 this 設(shè)為 any
類型,也就是說編譯器不會對 this 做類型檢查,就可以任意使用 this,比如:
function fn() { this.name = 'Naruto' this.age = 18 }
同時 TS 編譯器又提供了一個編譯選項 --noImplicitThis
,開啟后會檢查 this 的類型,此時需要明確指定其類型,否則會報錯,如下:
那么如何為 this 聲明類型呢?
聲明 this 類型
TS 函數(shù)中有一個特殊的 this 參數(shù),它用來指定該函數(shù)中用到的 this 的類型,需要定義在形參的第一個位置。
還是上面的例子,要為函數(shù)中的 this 指定類型的話,這樣寫:
function fn(this: {name: string, age: number}) { this.name = 'Naruto' this.xxx = 'xxx' }
直接在函數(shù)參數(shù)列表中聲明 this 類型不太優(yōu)雅,可以使用 type 關(guān)鍵字聲明別名再使用:
type Person = {name: string, age: number} function fn(this: Person) { this.name = 'Naruto' this.age = 18 }
當定義了 this 類型后,函數(shù)在調(diào)用時也會有所不同,需要使用 call、apply :
type Person = {name: string, age: number} function fn(this: Person, a: number) { this.name = 'Naruto' this.age = 18 } fn.call({name: 'Naruto', age: 18}, 10) fn.apply({name: 'Naruto', age: 18}, [10])
像以前那樣直接調(diào)用函數(shù)是錯誤的:
fn(10) // X
函數(shù)重載
面向?qū)ο缶幊逃腥筇卣鳎庋b、繼承和多態(tài)。多態(tài)的表現(xiàn)之一就是函數(shù)的重載。
函數(shù)重載,就是可以多次聲明一個同名函數(shù),但是它們的參數(shù)類型不同或者參數(shù)個數(shù)不同。這樣在調(diào)用時,可以根據(jù)傳入?yún)?shù)類型的不同,參數(shù)個數(shù)的不同,來確定執(zhí)行的到底是哪一個函數(shù)。
函數(shù)重載是后端語言的概念,比如 java 中:
// 兩個整數(shù)的和 public static int add(int a, int b) { return a+b; } // 三個整數(shù)的和 public static int add(int a, int b, int c) { return add(a,b)+c; }
JS 本身并不支持函數(shù)重載。如果多次聲明一個函數(shù),則后聲明的會覆蓋掉先聲明的。但是 JS 可以利用 arguments 對象,再加上判斷實參的類型,來模擬重載的功能,比如:
function add() { let args = Array.from(arguments) if(args.length == 2) { return args[0] + args[1] } else if(args.length == 3) { return args[0] + args[1] + args[3] } } add(1,2) add(1, 2, 3)
TS 中多次聲明一個同名函數(shù),編譯器會報錯。但是 TS 提供了實現(xiàn)函數(shù)重載的方法:先通過 function 關(guān)鍵字聲明重載的類型,最后寫函數(shù)的實現(xiàn)。
function add(a: number, b: number) : number function add(a: string, b: string) : string function add(a: number|string, b: number | string) { if(typeof a === 'number' && typeof b === 'number') { return a + b } else if(typeof a === 'string' && typeof b === 'string') { return a + b } } add(1, 2) add('10', '20')
由于在聲明重載時已經(jīng)確定了函數(shù)的返回值類型,在寫函數(shù)實現(xiàn)時,就不再需要寫返回值類型了。編譯器會根據(jù)重載類型自動推導(dǎo)。
TS 的函數(shù)重載只是一種偽重載,最終還是要靠去判斷類型,來執(zhí)行不同的邏輯。
還有一點要注意,聲明函數(shù)重載和函數(shù)實現(xiàn)必須寫在一塊,中間不能插入其他語句。
總結(jié)
本文介紹了TS 中有關(guān)函數(shù)的知識,包括函數(shù)的聲明方式,如何聲明函數(shù)類型,函數(shù)參數(shù)和返回值的類型,函數(shù)重載以及 this 的類型。大部分內(nèi)容和 JS 中差不太多,主要是 this 類型和函數(shù)重載這兩點,需要額外關(guān)注下。
以上就是如何在TypeScript中使用函數(shù)的詳細內(nèi)容,更多關(guān)于TypeScript 函數(shù)使用的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
d3.js實現(xiàn)簡單的網(wǎng)絡(luò)拓撲圖實例代碼
最近一直在學習d3.js,大家都知道d3.js是一個非常不錯的數(shù)據(jù)可視化庫,我們可以用它來做一些比較酷的東西,比如可以來顯示一些簡單的網(wǎng)絡(luò)拓撲圖,這篇文中就通過實例代碼給大家介紹了如何利用d3.js實現(xiàn)簡單的網(wǎng)絡(luò)拓撲圖,有需要的朋友們可以參考借鑒,下面來一起看看吧。2016-11-11淺談js之字面量、對象字面量的訪問、關(guān)鍵字in的用法
下面小編就為大家?guī)硪黄獪\談js之字面量、對象字面量的訪問、關(guān)鍵字in的用法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-11-11JavaScript編寫Chrome擴展實現(xiàn)與瀏覽器的交互及時間通知
得益于API,我們可以用JavaScript編寫Chrome擴展實現(xiàn)與瀏覽器的交互及時間通知。值得一提的是現(xiàn)在Chrome擁有后臺進程可以使通知在前臺瀏覽器關(guān)閉的情況下依然能夠生效.2016-05-05IE6,IE7,IE8下使用Javascript記錄光標選中范圍(已補全)
IE6,7,8下使用Javascript記錄光標選中范圍(已補全)(已解決單個節(jié)點內(nèi)部重復(fù)字符的問題)2011-08-08