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里的处理流程相似。先查找重载列表,尝试使用第一个重载定义,如果匹配的话就使用这个。因此,在定义重载的时候,一定要把最精确的定义放在最前面。