普通定义
let a = 100;
function getNum(x,y){
return a + x + y;
}
console.log(getNum(1,3))
为函数定义类型
function add(x: number, y: number): number{
return x + y;
}
// 可以为函数体本身添加返回值类型,由于TS会根据返回语句自动推断出返回值类型,因此可以省略
let myAdd = function(x: number, y: number): number {
return x + y;
}
完整的函数类型
函数类型包含两部分:
- 参数类型
- 返回值类型
// 完整的书写方式应该两个方面都提现出来
let meAdd: (x: number, y: number) => number = function(x: number, y: number): number {
return x + y;
}
推断类型
函数定义时,如果赋值语句的一边指定了类型但另一边没有类型的话,TS会自动识别出类型
// 右边指定了类型
let typeAdd = function(x: number, y: number): number { return x + y; };
// 左边指定了类型
let typeAdd1: (baseValue: number, increment: number) => number = function(x, y) { return x + y; }
可选参数跟默认参数
- TS中每个函数的参数都是必须的,传递给一个函数的参数个数必须与函数期望的参数个数一致
- S中可以在参数名旁边使用?实现可选参数功能。可选参数必须跟在参数后面
- TS中可以给参数提供一个默认值当用户没有传递这个参数或者传undefined时,使用默认值,默认参数的位置没有要求但是,如果带默认值的参数放在必须参数前面,用户必须明确的传入undefined来获取默认值
- 可选参数或者默认参数在调用时都可以省略
function buildName(firstName: string, lastName: string){
return firstName + ' ' + lastName;
}
// let resutl1 = buildName('Bob'); // error 参数个数不够
// let result2 = buildName('Bob', 'Admas', 'Sr'); // error 参数个数超出
let result3 = buildName('Bob', 'Admas'); // Ok
// 可选参数
function buildMyName(firstName: string, lastName?: string){
if(lastName){
return firstName + ' ' + lastName;
}else{
return firstName;
}
}
let res1 = buildMyName('Bob'); // Ok
let res2 = buildMyName('Bob', 'Admas'); // Ok
// let res3 = buildMyName('Bob', 'Admas', 'Sr'); // error 参数超出
// 设置默认值
function buildDefaultName(firstName: string, lastName = "Smith"){
return firstName + ' ' + lastName;
}
let rest1 = buildDefaultName('Bob'); // Ok
let rest2 = buildDefaultName('Bob', undefined); // Ok
// let rest3 = buildDefaultName('Bob', 'Admas', 'Sr'); // error 参数多余
let rest4 = buildDefaultName('Bob', 'Admas'); // Ok
剩余参数
TS中可以把所有参数收集到一个变量里:用...表示
剩余参数会被当做个数不限的可选参数,可以是0到多个
function buildOtherName(firstName: string, ...restOfName: string[]){
return firstName + ' ' + restOfName.join(' ');
}
let ohters = buildOtherName('Bob', 'Admas', 'jjzhang','hahaa', 'kdddd');
函数中的this
- 在JS中,只有在函数被调用的时候才会指定this的值
- 顶级的非方法式调用会将this视为window对象
- 箭头函数能保存函数创建时的this值,而不是调用时的值
- 如果设置了noImplicitThis标记,TS会指出当this为window时,this的类型为any
let deck = {
suits: ['hearts', 'spades', 'clubs', 'dismonds'],
cards: Array(52),
createCardPicker: function() {
return function() {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 3);
// 此时this指向window
return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
}
},
createCardPicker1: function() {
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 3);
// 此时this.suits的类型为any类型,因为this来自对象字面量里的函数表达式
return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
}
}
}
let cardPicker = deck.createCardPicker1();
let pickedCard = cardPicker();
console.log('card: ' + pickedCard.card + ' of ' + pickedCard.suit);
// this参数
interface Card {
suit: string;
card: number;
}
interface Deck {
suits: string[];
cards: number[];
createCardPicker(this: Deck): () => Card;
}
let deck1: Deck = {
suits: ['hearts', 'spades', 'clubs', 'dismonds'],
cards: Array(52),
createCardPicker: function(this: Deck) {
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 3);
// 此时this的类型就不是any而是Deck实例了
return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
}
}
}
let cardPicker1 = deck1.createCardPicker();
let pickedCard1 = cardPicker1();
console.log('card: ' + pickedCard1.card + ' of ' + pickedCard1.suit);
重载
- 为同一个函数提供多个函数类型定义来进行函数重载,编译器会根据这个列表去处理函数的调用
- TS查找重载列表,尝试使用第一个重载定义,如果匹配就用这个不匹配继续向下查找,所以在定义重载时,需要把最精确的定义放在最前面
- 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 pickCard = Math.floor(Math.random() * x.length);
return pickCard;
}else if(typeof x == 'number'){
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13 };
}
}
// 调用时重载的函数会进行正确的类型检查
let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
let pickedCard3 = myDeck[pickCard(myDeck)];
console.log("card: " + pickedCard3.card + " of " + pickedCard3.suit);
let pickedCard2 = pickCard(15);
console.log("card: " + pickedCard2.card + " of " + pickedCard2.suit);
网友评论