从0开始学习TypeScript-函数

102 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1.我们认识的函数

今天开始学习Typescript的函数,可以这么说函数是JavaScript应用程序的基础,它帮助我们实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要提供定义行为,和JavaScript一样,TypeScript函数可以创建有名字的函数和匿名函数,可以随意选择适合应用程序的方式,不论是定义一系列API函数还是只使用一次的函数。

//js函数
function func(x, y) {
    return x + y;
}
//js函数字面量赋值
let func = function(x, y) { return x + y; };

在TypeScript中我们来为上面的函数添加返回类型为number,TypeScript能够根据返回语句自动推断出返回值类型,因此我们可以忽略明确的写出返回类型,个人建议还是写上,可读性高一些,也不是每个人都要深入方法中去读取您的逻辑

//返回值为number
function func(x: number, y: number): number {
    return x + y;
}

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

函数类型包含两部分:参数类型和返回值类型。 当写出完整函数类型的时候,这两部分都是需要的。 我们以参数列表的形式写出参数类型,为每个参数指定一个名字和类型。 这个名字只是为了增加可读性。 我们也可以这么写:

//字面量赋值
let func: (baseValue: number, increment: number) => number =
function(x: number, y: number): number { return x + y; };
2.可选参数和默认参数

TypeScript里的每个函数参数都是必须的,我们也可以传递null或undefined作为参数,但是Typescript 设计的原因也带有一些静态语言的意思,就是声明了形参必须传入对应的实参,而可选参数必须跟在必须参数后面

//使用问号代表参数是可选的
function build(firstName: string, lastName?: string) {
    return firstName + " " + lastName;
}
//下面2种实参传递都可以
let result1 = build("参数1");  
let result3 = build("参数1", "参数2");       

我们发现和JavaScript不同的是,Javascript每个参数都是可选的,可传可不传。 没传参的时候,它的值就是undefined。

3.剩余参数

我们在JavaScript里,可以使用 arguments来访问所有传入的参数,但在TypeScript里,我们同样可以把所有参数收集到一个变量里,我们称之为剩余参数,剩余参数会被当做个数不限的可选参数,可以一个都没有,同样也可以有任意个。 编译器创建参数数组,名字是省略号( ...)后面给定的名字,我们可以在函数体内使用这个数组。

//例如把变量参数放到restOfName中,它是一个列表
function build(first: string, ...restOfName: string[]) {
  return first + " " + restOfName.join(" ");
}

let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
4.this和箭头函数

JavaScript里,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);

可以看到createCardPicker是个函数,并且它又返回了一个函数,如果我们运行这个程序,会发现它并没有弹出对话框而是报错了。 因为 createCardPicker返回的函数里的this被设置成了window而不是deck对象。 因为我们只是独立的调用了 cardPicker()。 顶级的非方法式调用会将 this视为window。 (注意:在严格模式下, this为undefined而不是window)。

为了解决这个问题,我们可以在函数被返回时就绑好正确的this。 这样的话,无论之后怎么使用它,都会引用绑定的‘deck’对象。 我们需要改变函数表达式来使用ECMAScript 6箭头语法。 箭头函数能保存函数创建时的 this值,而不是调用时的值

let deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    createCardPicker: function() {
        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);