TypeScript-(三)函數

函數的定義方式

指定型態

TypeScript 跟 JavaScript 的函數的宣告語法很相似,但是 TypeScript 可以指定「傳入參數的型別」以及「回傳值型別」。

1
2
3
function 函數名稱(參數名稱:型別,...):回傳值型別{
...處理內容...
}

在小括號中一樣可以傳入多個參數並以逗點分割,但是每個參數都可以使用分號指定型別;接著後面用分號指定回傳值型別。

以下範例:

1
2
3
function calc(price:number,count:number):string{
return "Total:"+price*count;
}

如果函數沒有回傳值,則可以指定回傳值為「void」,如下:

1
2
3
function click():void{
...
}

選擇性參數

有些情況,函數中的部分參數並非必傳值,而是開放性的 option,因此可以用「?」符號來代表它是可以忽略的參數,而當沒有傳入該參數時,在函數中其會以賦予「undefined」值。

1
2
3
4
5
6
7
8
9
10
11
12
13
function calc(price:number,tax?:number):number{
let tx = 0;
if(tax){
tx = tax;
}else{
tx = 0.05;
}

return Math.floor(price*(1+tx));
}

console.log(calc(100));//印出105
console.log(calc(100,0.1));//印出110

多載(Overload)

在撰寫一個函數功能時,可能會發生該函數在不同情況會有「相異型別的傳入參數」或「相異型別的回傳值」,可是在 JavaScript 中,「函數名稱」就不能重複宣告,如下方的情況:

1
2
3
4
5
6
function convert(name,index){
// ...
}
function convert(age,index){//merge重複宣告,覆蓋前一個merge函數
// ...
}

而透過 TypeScript,當參數或回傳值的型別不同時,則可以同時接受多個同名函數。

不過並非直接寫入多個同名函數,而是鮮血函數的宣告敘述,在彙整函數的處理內容,如下語法範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function convert(info:number):boolean;
function convert(info:string):string;
function convert(info:string,note:string):string;
function convert(info:boolean):string;

function convert(info:any,note?:string):any{
switch(typeof info){
case number:
return info>18?true:false;
case string:
return info+(note?("-"+note):"");
case boolean:
return info?"yes":"no";
}
}

泛型(Generics)

當函數可以接受各種狀況的參數及回傳值時,我們可以使用any作為型別,不過有個問題是我們無法確認傳入與回傳的型別為何。

1
2
3
function identity(arg: any): any {
return arg;
}

假設我需要確保傳入跟傳出的型別相同,就可以使用泛型。使用<>符號自定義一個「型別變數」,作為取得的參數的型別,如下範例:

1
2
3
function identity<T>(arg:T):T{
return arg;
}

上述的 T 為型別變數名稱,用來儲存參數的型別。在函數執行時,辨識傳入參數 arg 的型別並賦予值給 T。

在呼叫使用函數時,可以如一般情況只傳入參數,編譯器會自動辨識傳入參數的型別用以定義型別變數 T ;或者也可以同時使用<>傳入型別變數。兩種情況如下範例:

1
2
3
4
5
//只傳入參數
console.log(identity(123));//印出 number 型別的123

//傳入參數、型別變數
console.log(identity<string>("hello"));//印出 string 型別的hello

可變數量參數

函數中的參數量若不固定,TypeScript 支援「可變量參數」,讓函數可以接受型別相同但數量不定的資料。

1
2
3
function 函數名稱(...參數:型別){
...
}

在參數前方加上「…」,則這個參數變數就會被視為可變量的,不論傳入多少個參數,只要是同型別,都能被函數處理。如下範例:

1
2
3
4
5
6
7
8
9
10
function sum(...item:number[]):number{
let total:number = 0;
for(let i:number=0 ; i<item.length ; i++){
total = total + item[i];
}
return total;
}

console.log(sum(1,2,3,4,5)); //印出 15
console.log(sum(1,2,3,4,5,6,7,8,9,10)); //印出 55

可以看到 ...item:number[],這邊就適當所有參數傳入函數中,會被當作一個number型別的陣列做處理,並且存為一個名為 item 的變數中。

箭頭函式(Arrow Function)

除了使用 function 關鍵語法定義函式,TypeScript 也提供更簡易的箭頭函式,目前也已經被ES6所採用。

1
2
3
(參數1,參數2,...)=>{
...執行內容...;
}

箭頭函式最主要的優點是「方便把整段函式當作一個資料值來使用」,而如果最終執行結果只有一行,且是一個回傳值,可以省去執行內容的大括號,以下舉例:

1
2
3
4
5
6
7
8
9
(n)=>{
return n*n;
}

//更簡化
(n)=>n*n;

//指定參數型別
(n:number)=>n*n;

如果想宣告一個變數,定且存入整段函數,同時去指定參數的型別及回傳值的型別,寫法如下:

1
let func:(number) => number = (n:number)=> n*n;

上方案例中,先宣告一個變數 func,冒號後方指定其型別為(number)=>number,意思是指定參數的型別為numebr、回傳值的型別指定為number;最後使等號存入值為 (n:number)=>n*n 這樣僅有一行的內容。

也因為箭頭函式簡略的特性,最常被使用的地方就是「將箭頭函式當作函式中的參數」,如下範例:

1
2
3
4
5
6
7
8
9
10
11
function print(n:number,func:(number)=>string){
let re:number = func(n);
return re;
}


let aFunc:(number)=>string = (n:number)=>"<面積>"+(n*n);
let bFunc:(number)=>string = (n:number)=>"<體積>"+(n*n*n);

console.log(print(5,aFunc));
console.log(print(5,bFunc));

© 2020 Leah's Blog All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero