Web/05-JavaScript基础:ES6语法/06-ES6:箭头函数.md
2021-07-29 11:08:52 +08:00

223 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 06-ES6箭头函数
publish: true
---
<ArticleTopAd></ArticleTopAd>
## 前言
ES6 在**函数扩展**方面,新增了很多特性。例如:
- 箭头函数
- 参数默认值
- 参数结构赋值
- 剩余参数
- 扩展运算符
- this 绑定
- 尾调用
今天这篇文章,我们讲一下箭头函数。
## 箭头函数
### 定义箭头函数的语法
语法:
```js
(参数1, 参数2 ...) => { 函数体 }
```
解释:
- 如果有且仅有 1 个形参,则`()`可以省略
- 如果函数体内有且仅有 1 条语句,则`{}`可以省略,但前提是,这条语句必须是 return 语句。
需要强调的是,箭头函数是没有函数名的,既然如此,那要怎么调用箭头函数呢?你可以将箭头函数赋值给一个变量,通过变量名调用函数;也可以直接使用箭头函数。我们来看看下面的例子。
### 举例
写法 1、定义和调用函数传统写法
```javascript
function fn1(a, b) {
console.log('haha');
return a + b;
}
console.log(fn1(1, 2)); //输出结果3
```
写法 2、定义和调用函数ES6 中的写法)
```javascript
const fn2 = (a, b) => {
console.log('haha');
return a + b;
};
console.log(fn2(1, 2)); //输出结果3
```
上面的两种写法,效果是一样的。
从上面的箭头函数中,我们可以很清晰地看到变量名、参数名、函数体。
另外,箭头函数的写法还可以精简一下,继续往下看。
在箭头函数中,如果方法体内只有一句话,且这句话是 return 语句,那就可以把 `{}`省略。写法如下:
```javascript
const fn2 = (a, b) => a + b;
console.log(fn2(1, 2)); //输出结果3
```
在箭头函数中,如果形参只有一个参数,则可以把`()`省略。写法如下:
```js
const fn2 = (a) => {
console.log('haha');
return a + 1;
};
console.log(fn2(1)); //输出结果2
```
## 箭头函数的 this 的指向
> 箭头函数只是为了让函数写起来更简洁优雅吗?当然不只是这个原因,还有一个很大的作用是与 this 的指向有关。
ES6 之前的普通函数中this 指向的是函数被调用的对象也就是说谁调用了函数this 就指向谁)。
而 ES6 的箭头函数中:**箭头函数本身不绑定 this**this 指向的是**箭头函数定义位置的 this**也就是说箭头函数在哪个位置定义的this 就跟这个位置的 this 指向相同)。
代码举例:
```js
const obj = { name: '千古壹号' };
function fn1() {
console.log(this); // 第一个 this
return () => {
console.log(this); // 第二个 this
};
}
const fn2 = fn1.call(obj);
fn2();
```
打印结果:
```
obj
obj
```
代码解释:(一定要好好理解下面这句话)
上面的代码中,箭头函数是在 fn1()函数里面定义的,所以第二个 this 跟 第一个 this 指向的是**同一个位置**。又因为,在执行 `fn1.call(obj)`之后,第一个 this 就指向了 obj所以第二个 this 也是指向 了 obj。
### 面试题:箭头函数的 this 指向
代码举例:
```js
var name = '许嵩';
var obj = {
name: '千古壹号',
sayHello: () => {
console.log(this.name);
},
};
obj.sayHello();
```
上方代码的打印结果是什么?你可能很难想到。
正确答案的打印结果是`许嵩`。因为 `obj` 这个对象并不产生作用域, `sayHello()` 这个箭头函数实际仍然是定义在 window 当中的,所以 这里的 this 指向是 window。
## 参数默认值
**传统写法**
```javascript
function fn(param) {
let p = param || 'hello';
console.log(p);
}
```
上方代码中,函数体内的写法是:如果 param 不存在,就用 `hello`字符串做兜底。这样写比较啰嗦。
**ES6 写法**:(参数默认值的写法,很简洁)
```javascript
function fn(param = 'hello') {
console.log(param);
}
```
在 ES6 中定义方法时,我们可以给方法里的参数加一个**默认值**(缺省值):
- 方法被调用时,如果没有给参数赋值,那就是用默认值;
- 方法被调用时,如果给参数赋值了新的值,那就用新的值。
如下:
```javascript
var fn2 = (a, b = 5) => {
console.log('haha');
return a + b;
};
console.log(fn2(1)); //第二个参数使用默认值 5。输出结果6
console.log(fn2(1, 8)); //输出结果9
```
**提醒 1**:默认值的后面,不能再有**没有默认值的变量**。比如`(a,b,c)`这三个参数,如果我给 b 设置了默认值,那么就一定要给 c 设置默认值。
**提醒 2**
我们来看下面这段代码:
```javascript
let x = 'smyh';
function fn(x, y = x) {
console.log(x, y);
}
fn('vae');
```
注意第二行代码,我们给 y 赋值为`x`,这里的`x`是括号里的第一个参数,并不是第一行代码里定义的`x`。打印结果:`vae vae`。
如果我把第一个参数改一下,改成:
```javascript
let x = 'smyh';
function fn(z, y = x) {
console.log(z, y);
}
fn('vae');
```
此时打印结果是:`vae smyh`。
## 我的公众号
想学习**更多技能**?不妨关注我的微信公众号:**千古壹号**。
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
![](https://img.smyhvae.com/20200102.png)