# 函数的扩展
# 箭头函数
ES6中可以用箭头定义函数
# 基础用法
- 常规定义法
//函数名 = (参数) => {函数体}
let fn = () => {
console.log('this is a arrow function');
}
fn();
1
2
3
4
5
2
3
4
5
- 省略写法
- 省略参数括号:当参数为一个时,可以省略括号。
- 省略函数体换括号:当函数体内只有一个return语句时可以省略花括号,并且省略return关键字,直接写后面的语句。
//(1)参数括号省略
let fn1 = num => {
console.log(num);
}
fn1(7);
//(2)函数体花括号省略
let fn2 = num2 => console.log(num2);
fn2(77);
//(3)都省略一下看看:
let fn3 = num3 => num3 + 1;
console.log(fn3(776));
//这个等价于:
// let fn3 = (num3) => {
// return num3 + 1;
// }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
当欲用省略方式,函数体内部返回一个对象时,要在外层加一个括号。
// let fn5 = num5 => {name: 'zs', age: 'ls'}; //报错
let fn5 = num5 => ({name: 'zs', age: 'ls'});
1
2
2
- 箭头函数参数可以与变量解构赋值相结合,简化代码书写
let obj = {
first: 'Tony',
last: 'Stark'
}
let fn = ({first:firstName, last:lastName} = obj) => firstName + ' ' + lastName;
console.log(`This man is named ${fn()}`);
// This man is named Tony Stark
1
2
3
4
5
6
7
2
3
4
5
6
7
# this指向
- 箭头函数this是固定的,直观上可以理解为,绑定定义时所在的作用域,而不是指向运行时所在的作用域。
- 从底层上看,箭头函数的执行上下文中没有this,this其实是外部执行上下文的this。
- 在判断箭头函数的this指向性问题时,要从外部的执行上下文找。
// 箭头函数执行上下文中的this指向
const num = 1
const obj = {
num: 2
}
function fn () {
// 2. 执行流进入fn,触发延时器
// 回调为箭头函数,无this,this来自外部执行上下文
setTimeout (() => {
// 3. 所以,这个this为fn的this,自然指向obj,而不是原来的window
console.log(this.num);
}, 1000);
};
//1. 调用call()使fn中的this指向obj
fn.call(obj);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
将上述fn函数转换成对应的ES5代码,会容易理解:
function fn() {
var _this = this;
setTimeout( function () {
console.log(_this.num);
}, 1000);
};
1
2
3
4
5
6
2
3
4
5
6
- 箭头函数不适合使用的场景
由箭头函数特殊的this指向,使得this从“动态”变成“静态”。
- 不可以作为构造函数: 由于箭头函数特殊的this指向,而构造函数this指向实例,所以自然不可以用作构造函数
- 不适合用在对象中的方法上
- 不适合需要动态变化this指向的情况
// 解释第二点
const obj = {
num: 7,
fn: () => {
this.num++;
}
}
obj.fn();
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
上例中,本意是obj.fn()
,对象调用法,调用fn处理obj内部的num,但是使用了箭头函数定义fn,这就导致this来自外部,由于对象obj没有指向上下文,那就只能使全局执行上下文,所以this,指向了window。
# 特征总结
- 箭头函数的执行上下文中没有this,this其实是外部执行上下文的this。
- 箭头函数没有arguments伪数组,可用rest参数替代。
- 箭头函数不可以作为构造函数。