TS中的函數擴充功能
完整函數類型
//js定義函數 function add(x, y) { return x + y; } //ts中定義完整函數 let add: (x: number, y: number) => number = function(x: numer, y: number):number { return x + y; } //函數中的參數並非要和型別宣告中的參數保持一致,只要參數類型保持一致即可 function (baseValue: number, increment: number) { return x + y; } //當然,你也可以利用ts中的類型推斷功能,不需要在函數中聲明參數類型,ts會根據上下文自動進行檢查,如: let add: (x: number, y: number) => number = function(x,y){return x + y;} //這就是ts中定義函數的好處,時刻讓你知道自己當初的想法,不讓你偏離原來的軌道, //時刻來約束你,不讓你犯錯,哈哈
選擇性參數和預設參數
//在js中,每個參數都是可選,可傳可不傳,沒傳的話,其值就是undefined.但在ts中,就沒那麼舒服了。定義的函數參數個數是多少,你就必須傳多少,不能多也不能少,否則,就會報錯 function buildName(firstName: string, lastName: stirng){ return firstName + " " + lastName; } let result1 = buildName("Bob"); //error let result2 = buildName("Bob", "Yu"); //right let result3 = bulidName("Bob", "Yu" , "Sr."); //error //ts中選擇性參數的表示方法 //而且,還需要注意是,選擇性參數必須跟在必選參數的後面,這個順序不能亂 function buildName(firstName: string, lastName?: string){ if(lastName){ return firstName + " " + lastName; }else{ return firstName; } } //ts中的預設參數表示方法 //在ts中當使用者沒有傳遞這個參數或傳遞的值是undefined時,如果你願意,你就可以將這個參數設為預設參數,即預設初始化值的參數。 function buildName (firstName: string, lastName: string = "Smith"){ return firstName + " " + lastName; }
剩餘參數
必要參數,預設參數和選擇性參數有個共同點:即他們表示某一個參數。當你想同時操作多個參數,或者你並不知道會有多少參數傳遞進來。在js中,你可以使用arguments對象訪問,當然,在ts中也可以辦到。在ts中,我們將所有參數收集到一個數組中。
function buildName(firstName: stirng, ...restOfName: string[]){ return firstName + " " + restOfName.join(" "); }
this和箭頭函數
this很好,但一般好的東西,都求之而不得,哈哈
//js let deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), createCardPicker: function(){ return function(){ let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13); return { suit: this.suits[pickedSuit], card: pickedCard % 13 }; } } }; let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker(); console.log("card: " + pickedCard.card + " of " + pickedCard.suit); //如果嘗試運行上述程式,會發現並沒有彈出對話方塊,而是報錯了。因為createCardPicker返回的函數裡的this被設定成window而不是deck對象。 //為瞭解決這個問題,我們可以在函數被返回的時就綁好正確的this。而箭頭函數能儲存函數建立時的this值,而不是調用時的值。this + Ts簡直是絕配。 //ts改寫上述例子 interface Card { suit: string; card: number; } interface Deck { suits: string[]; cards: number[]; createCardPicker(this: Deck): () => Card; } let deck: Deck = { suits: ["hearts", "spades", "clubs", "diamonds"], card: Array(52), createCardPicker: function(this: Deck) { return () => { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13); return { suit: this.suits[pickedSuit], card: pickedCard % 13 }; } } } let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker(); console.log("card: " + pickedCard.card + " of " + pickedCard.suit);
重載
js中沒有重載,但可喜可賀,ts中可以使用重載
let suits = ["hearts", "spades", "clubs", "diamonds"]; function pickCard(x: {suit: string; card: number;}[]) : number; function pickCard(x: number) : {suit: string; card: number}; function pickCard(x) : any { if(typeof x == "object"){ let pickedCard = Math.floor(Math.random() * x.length); return pickedCard; } else if (typeof x == "number") { let pickedSuit = Math.floor(x / 13); return { suit: suits[pickedSuit], card: x % 13 }; } } //object let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }]; let pickedCard1 = myDeck[pickCard(myDeck)]; alert("card: " + pickedCard1.card + " of " + pickedCard1.suit); //number let pickedCard2 = pickCard(15); alert("card: " + pickedCard2.card + " of " + pickedCard2.suit); //注意:function pickCard(x): any 並不是重載列表的一部分,因此這裡只有兩個重載:一個是接收對象,另一個是接收數字。 //為了讓編譯器能夠選擇正確的檢查類型,它與javascript裡的處理流程相似。先尋找重載列表,嘗試使用第一個重載定義,如果匹配的話就使用這個。因此,在定義重載的時候,一定要把最精確的定義放在最前面。