> For the complete documentation index, see [llms.txt](https://yes-1-am.gitbook.io/blog/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yes-1-am.gitbook.io/blog/typescript-yu-fa/han-shu.md).

# 函数

## 1. 函数类型

### 1.1 为函数定义类型

具名函数

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

添加类型
function add(x:number, y:number): number {
    return x+y;
}
```

匿名函数

```
let add = function(x,y) {
    return x+y;
}

添加类型
let add = function(x:number,y:number):number {
    return x+y;
}
```

### 1.2 完整函数类型

```
// (x:number,y:number) => number 为函数类型
// (x:number,y:number) 为参数类型， => number 对应返回值类型。对于完整函数类型来说，这两部分都是需要的

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

// 其中，参数类型指定了名字和类型,如 x: number, x为名字，number为类型。而名字只是为了增加可读性，不存在实际的限制，如：  

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

此时参数类型的名字 baseValue 与 真正参数的名字 x 并不相同。我们只要参数类型匹配，就认为是有效的类型。
```

第二部分是返回值类型，如 `number`, 对于函数和返回值类型必须使用 `=>` 符号。返回值类型是函数类型的必要部分,如果没有返回值，必须指定为 `void`

**推断类型**

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

即赋值语句一边(如左边)指定了类型，而另一边(如右边)没有指定类型，TypeScript会自动识别出类型。

### 1.3 函数参数

TypeScript要求函数的实参个数和形参个数相等：

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

buildName('bob');    // error, 参数过少
buildName('bob','adams','sr');  // error, 参数过多
buildName('bob','adams');  // 正确
```

**可选参数**

```javascript
function buildName(firstName: string, lastName?: string) {
    return firstName + lastName;
}

buildName('1')  // 正确
buildName('1','2')  // 正确
```

可以使用 `?` 表示参数可选。 可选参数必须放在函数的*必须参数*后面。

**默认参数**

```javascript
function buildName(firstName: string, lastName='123') {
    return firstName + lastName;
}

buildName('1')  // 正确, 默认参数同样是可选的，此时实参不必和形参个数一样
buildName('1','2')  // 正确
```

可选参数函数和默认参数函数共享一个函数类型：`(firstName:string, lastName: string) => string`,此时默认参数的默认值消失了，只表示它是可选参数

和**可选参数函数**不同，**默认参数函数**的默认值参数不必放在*必须参数*后面，此时如果默认值参数出现在必须参数之前，那么必须明确传入 undefined 来获取默认值：

```javascript
function buildName(firstName='123', lastName:string) {
    return firstName + lastName;
}

buildName('bob') // error 实参太少，此时 firstName 为 bob， lastName 为 undefined
buildName(undefined, 'bob')  // 正确，firstName='123', lastName='bob'
```

**剩余参数**

```javascript
function buildName(firstName:string, ...restOfName: string[]) {
    return firstName + restOfName.join('-');
}

const employeeName = buildName('1','2','3','4');
// restOfName === [2,3,4]
```

剩余参数函数的类型:

```javascript
function buildName(firstName:string, ...restOfName: string[]) {
    return firstName + restOfName.join('-');
}

const buildFun: (name:string, ...rest: string[]) => string = buildName
```

## 2. this

### this和箭头函数

在js中，this的值只有在被调用的时候才会指定，而不是在定义函数的时候。

```
let deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    createCardPicker: function() {
        return function() {
            // 返回一个函数，且该函数为非方法式调用(不是object.method())
            // 那么 this 为 window，严格模式下为 undefined
            return this.suits
        }
    }
}

let cardPicker = deck.createCardPicker();
cardPicker();  // error, undefined 上没有 suits 属性
```

为了解决这个问题，可以在函数被返回时绑定好 `this` ，无论之后怎么调用，`this` 都是 `deck` 对象,而不是调用时的值：

```javascript
let deck = {
    suits: '123',
    createCardPicker: function() {
        return () => {
            // 通过箭头函数， this 绑定为 deck 对象
            return this.suits
        }
    }
}

let cardPicker = deck.createCardPicker();
cardPicker();  //  输出 '123'
```

更为友好的是，如果使用 TypeScript,且给编译器设置了 `--noImplicitThis` , 那么第一种情况里的 `this` 会认为是 `any` 类型，而第二种`this`是`deck`的类型。

**函数重载**

当需要某个方法，根据传入参数的类型不同，而返回不同类型的值时，就需要用到重载

```javascript
function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any {
    if (typeof x == "object") {
        ...
    }
    else if (typeof x == "number") {
        ...
    }
}
```

注意点

* 定义重载时，一定要把最精确的定义放在最前面
* `function pickCard(x): any` 不是重载列表的一部分，即pickCard函数只有两个重载，只能接受对象或者数字作为参数，其它参数则会报错 &#x20;


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yes-1-am.gitbook.io/blog/typescript-yu-fa/han-shu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
