1. 什么是箭头函数
1.1. 箭头函数简介
箭头函数的语法非常简单 (parameters) => { statements }
,箭头函数只能用赋值式写法,不能用声明式写法。看一下最简单的箭头函数表示法:1
2let sayHello = () => { console.log('Hello World'); }
sayHello(); // Hello World
1.2. 箭头函数的特点
和普通函数相比,箭头函数主要就是以下三个方面的特点:
- 更简化的代码语法
- 没有局部 this 的绑定
- 不绑定 arguments
2. 更简化的代码语法
2.1. 一般写法
(parameters) => { statements }
1
2
3
4
5
6
7
8
9
10
11
12// 求两个数的和并在控制台输出
// ES6
let sum = (a, b) => {
console.log(a + b);
return a + b;
}
// ES5
var sum = function(a, b) {
console.log(a + b);
return a + b;
};
2.2. 省略 () 的情况
如果只有一个参数,可以省略()
括号。parameters => { statements }
1
2
3
4
5
6
7
8
9
10
11
12// 求一个数的两倍,并输出
// ES6
let double = num => {
console.log(num * 2);
return num * 2;
}
// ES5
var double = function(num) {
console.log(num * 2);
return num * 2;
};
2.3. 省略 {} 的情况
如果返回值仅仅只有一个表达式(expression), 还可以省略大括号{}
。parameters => statements
1
2
3
4
5
6
7
8// 求一个数的两倍
// ES6
let double = num => num * 2;
// ES5
var double = function(num) {
return num * 2;
};
2.4. 特殊情况
如果箭头函数直接返回一个对象,必须在对象外面加上括号。1
2
3
4
5
6
7
8
9
10// ES6
let returnObj = () => ({name: "xiguapi", age: 23});
// ES5
var returnObj = function() {
return {
name: "xiguapi",
age: 23
}
};
3. 没有局部 this 的绑定
和一般的函数不同,箭头函数不会绑定 this
。 或则说箭头函数不会改变 this
本来的绑定。
我们用一个例子来说明:1
2
3
4function Counter() {
this.num = 0;
}
var a = new Counter(); // a.num 0
因为使用了关键字 new
构造,Count()
函数中的 this
绑定到一个新的对象,并且赋值给 a
。通过 console.log
打印 a.num
,会输出 0。
如果我们想每过一秒将 a.num
的值加 1,该如何实现呢?可以使用 setInterval()
函数。1
2
3
4
5
6
7
8
9
10
11
12
13function Counter() {
this.num = 0;
this.timer = setInterval(function add() {
this.num++;
console.log(this.num);
}, 1000);
}
var b = new Counter();
// NaN
// NaN
// NaN
// ...
首先函数 setInterval
没有被某个声明的对象调用,也没有使用 new
关键字,再之没有使用 bind
, call
和 apply
。setInterval
只是一个普通的函数。实际上 setInterval
里面的 this
绑定到全局对象 window
上了。
使用箭头函数!使用箭头函数就不会导致 this
被绑定到全局对象。1
2
3
4
5
6
7
8
9
10
11
12function Counter() {
this.num = 0;
this.timer = setInterval(() => {
this.num++;
console.log(this.num);
}, 1000);
}
var b = new Counter();
// 1
// 2
// 3
// ...
通过 Counter
构造函数绑定的 this
将会被保留。在 setInterval
函数中,this
依然指向我们新创建的 b
对象。
3. 不绑定 arguments
箭头函数还有一个比较有特点的地方就是其不绑定 arguments,即如果你在箭头函数中使用 arguments 参数不能得到想要的内容。1
2
3let arrowfunc = () => console.log(arguments.length)
arrowfunc()
// arguments is not defined
4. 注意点
- 箭头函数适合于无复杂逻辑或者无副作用的纯函数场景下,例如:用在 map、reduce、filter 的回调函数定义中
- 箭头函数的亮点是简洁,但在有多层函数嵌套的情况下,箭头函数反而影响了函数的作用范围的识别度,这种情况不建议使用箭头函数
- 箭头函数要实现类似纯函数的效果,必须剔除外部状态。所以箭头函数不具备普通函数里常见的 this、arguments 等,当然也就不能用 call()、apply()、bind() 去改变 this 的指向
- 箭头函数不适合定义对象的方法(对象字面量方法、对象原型方法、构造器方法),因为箭头函数没有自己的 this,其内部的 this 指向的是外层作用域的 this
- 箭头函数不适合定义结合动态上下文的回调函数(事件绑定函数),因为箭头函数在声明的时候会绑定静态上下文
1 | const json = {bar: 1, fn: () => console.log(this.bar)}; |
1 | function Foo() { |
1 | const Message = (text) => { |
1 | const button = document.querySelector('button'); |