TypeScript学习系列(四)函数

声明:本学习系列参考了TypeScript3.3英文版官网教程

函数

typescript对标准的js函数增加了一些新的特性来让它更容易使用,typescript支持匿名函数和命名函数函数

function add(x: number, y: number): number {
    return x + y;
}

let myAdd = function(x: number, y: number): number { return x + y; };

1、完整的函数类型

完整的函数类型包括两个部分:参数列表和返回值类型。返回值类型使用=>表示。

let myAdd: (x: number, y: number) => number =
    function(x: number, y: number): number { return x + y; };

参数名称不一定要相同,只要它的顺序和类型匹配即可上例也可以改写成

let myAdd: (baseValue: number, increment: number) => number =
    function(x: number, y: number): number { return x + y; };

1.1、推断类型

如果你只在等式的一边指定来函数类型,为另一边没有指定,typescript会自动推断出你函数类型。

// myAdd has the full function type
let myAdd = function(x: number, y: number): number { return  x + y; };

// The parameters 'x' and 'y' have the type number
let myAdd: (baseValue: number, increment: number) => number =
    function(x, y) { return x + y; };

2、可选参数个默认参数

在js中每一个参数都是可选的,如果不传入就默认为undefined,但是在typescript中每一个参数都假设是必须的,换句话说就是所给的实参必须匹配函数的形参列表,不能多也不能少。

function buildName(firstName: string, lastName: string) {
    return firstName + " " + lastName;
}

let result1 = buildName("Bob");                  // error, too few parameters
let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result3 = buildName("Bob", "Adams");         // ah, just right

我们可以在参数名后添加?来设置可选参数,可选参数必须放在必传参数的后面。

function buildName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}

let result1 = buildName("Bob");                  // works correctly now
let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result3 = buildName("Bob", "Adams");         // ah, just right

我们也可以使用默认参数,如果没有传入值或者传入值是undefined就会使用默认参数,默认参数可以放在参数列表的任何地方,如果放在了必传参数的前面,则必须显示的传入undefined

function buildName(firstName = "Will", lastName: string) {
    return firstName + " " + lastName;
}

let result1 = buildName("Bob");                  // error, too few parameters
let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result3 = buildName("Bob", "Adams");         // okay and returns "Bob Adams"
let result4 = buildName(undefined, "Adams");     // okay and returns "Will Adams"

3、剩余参数

如果你想传入多个值到函数里,可以使用剩余参数,它会把你传入的剩余参数保存在一个数组里,使用...来定义一个剩余参数。

function buildName(firstName: string, ...restOfName: string[]) {
    return firstName + " " + restOfName.join(" ");
}

let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

4、this

4.1this的使用

在js怎样使用this就好像一场成年礼

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();

alert("card: " + pickedCard.card + " of " + pickedCard.suit);

这段代码会报错,因为调用函数时的this是指向window的而不是deck。可以使用es6的箭头函数来修复这个问题

let deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    createCardPicker: function() {
        // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
        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();

alert("card: " + pickedCard.card + " of " + pickedCard.suit);

虽然我们使用箭头函数解决了这个问题,但我们仍然不知道this的具体类型,如果你在编译器中传入来--noImplicitThis标志时,它将会指出this.suits[pickedSuit]this的类型是any,为了修复这个问题我们可以显示的传入一个this参数作为第一个参数。

interface Card {
    suit: string;
    card: number;
}
interface Deck {
    suits: string[];
    cards: number[];
    createCardPicker(this: Deck): () => Card;
}
let deck: Deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    // NOTE: The function now explicitly specifies that its callee must be of type Deck
    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();

alert("card: " + pickedCard.card + " of " + pickedCard.suit);

现在编译器知道thisDeck的类型了,所以--noImplicitThis就不会报错了。

4.2回调函数中的this

你可能在回调函数中使用this出错,例如如果一个库的作者指定了回调中this的类型

interface UIElement {
    addClickListener(onclick: (this: void, e: Event) => void): void;
}

这里作者把回调的this设置为void,意味着函数中不需要使用this,如果你在回调中传入了不是void类型的this,编译器将会报错。

class Handler {
    info: string;
    onClickBad(this: Handler, e: Event) {
        // oops, used this here. using this callback would crash at runtime
        this.info = e.message;
    }
}
let h = new Handler();
uiElement.addClickListener(h.onClickBad); // error!

5、函数重载

在js中函数通过传入不同的参数来返回不同类型的对象是很常见的事情,在typescript里可以使用函数重载来实现,对同一个函数使用多个函数类型来表示重载,编译器会查找重载列表,直到找到第一个匹配的为止,因此要把最精确的放在前面。

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 {
    // 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") {
        let pickedCard = Math.floor(Math.random() * x.length);
        return pickedCard;
    }
    // Otherwise just let them pick the card
    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 pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);

注意这里的function pickCard(x): any并不是重载列表的一部分,这里只有两个重载,一个接受对象,一个接受数字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值