在 JavaScript 中,有兩種方式定義方法。
1、命名的方法
function add(x,y){ return x+y; }
2、匿名方法
var myAdd = function(x,y) { return x+y;};
在 TypeScript 中,也兼容上面兩種定義方式,但是,既然我們用的是 TypeScript,那么肯定要強於本來的定義方式。
1、類型化方法
function add(x:number, y:number):number{ return x+y; } var myAdd = function(x:number, y:number):number {return x+y;};
為參數和返回值定義好類型,有助於智能感知和程序邏輯。
2、函數類型變量
在上面第一點,myAdd 變量的類型我們沒有指定,完整的寫法如下:
var myAdd: (x:number, y:number)=>number = function(x:number, y:number):number { return x+y; };
當然類型參數的命名可以不相同的
var myAdd: (baseValue:number, increment:number)=>number = function(x:number, y:number):number {return x+y;};
3、可選參數
function buildName(firstName: string, lastName?: string):string{ if(lastName){ return firstName + " " + lastName; } else{ return firstName; } }
在參數名后面,冒號前面添加一個問號,則表明該參數是可選的。
4、默認參數
function buildName(firstName: string, lastName = "Smith"):string { return firstName + " " + lastName; }
如果不傳入第二個參數,那么將會被賦值為默認值。
注:可選參數和默認參數必須在參數列表的最后。
5、可變參數
function buildName(firstName: string, ...restOfName: string[]) { return firstName + " " + restOfName.join(" "); } var employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
在參數名前面使用三個點表明該參數的個數是可變的,同樣,也是必須在參數列表的最后。
6、lambda 和當前對象
在 JavaScript 中,this 關鍵字指代的是當前 function。那么我們就很有可能在定義方法時用錯。參考下面:
var deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), createCardPicker: function() { return function() { var pickedCard = Math.floor(Math.random() * 52); var pickedSuit = Math.floor(pickedCard / 13); return {suit: this.suits[pickedSuit], card: pickedCard % 13}; } } } var cardPicker = deck.createCardPicker(); var pickedCard = cardPicker(); alert("card: " + pickedCard.card + " of " + pickedCard.suit);
那么在調用 createCardPicker 方法的時候,我們將不會得到預期的結果,因為 this 指的是當前 function,而不是 deck 對象。
為了解決這一點,TypeScript 引入 lambda 表示法
var deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), createCardPicker: function() { // Notice: the line below is now a lambda, allowing us to capture 'this' earlier return () => { var pickedCard = Math.floor(Math.random() * 52); var pickedSuit = Math.floor(pickedCard / 13); return {suit: this.suits[pickedSuit], card: pickedCard % 13}; } } } var cardPicker = deck.createCardPicker(); var pickedCard = cardPicker(); alert("card: " + pickedCard.card + " of " + pickedCard.suit);
那么現在 this,就指代 deck 對象了。
7、方法重載
因為 JavaScript 的語法,所以是不存在重載的。只要你在 JavaScript 中定義了一個方法,那么傳入多少個參數都是可以的。但是,從我們上面 TypeScript 的例子中,可以看出 TypeScript 是會檢查參數個數、類型是否匹配的。因此 TypeScript 中是有必要存在重載。
var 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 { // Check to see if we're working with an object/array // if so, they gave us the deck and we'll pick the card if (typeof x == "object") { var pickedCard = Math.floor(Math.random() * x.length); return pickedCard; } // Otherwise just let them pick the card else if (typeof x == "number") { var pickedSuit = Math.floor(x / 13); return { suit: suits[pickedSuit], card: x % 13 }; } } var myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }]; var pickedCard1 = myDeck[pickCard(myDeck)]; alert("card: " + pickedCard1.card + " of " + pickedCard1.suit); var pickedCard2 = pickCard(15); alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
上面代碼是 TypeScript 官方的例子,其實可以看出,我們方法體都需要寫在一個參數類型、返回類型為 any 的方法中。所以看上去其實有點自欺欺人的意思。方法重載在 TypeScript 中的意義主要在於智能提示。