箭头函数其实就是一种新的匿名函数写法,但是这种匿名函数和以前学过的匿名函数并不一样,最大的区别在于 this 指向。
在以前,this 指向是在函数调用时绑定的,谁调用的函数,this 就指向谁,如果直接调用函数,this 就会指向全局对象,如果通过 new 调用函数,this 会指向新创建的对象,如果是 DOM 事件处理函数,this 会绑定为事件源,当然,我们也可以使用 call,apply,bind 来手动绑定 this。
实际上,从本质上来说,this 到底指向谁,都取决于你怎么去用这个函数。在一些情况下,这个 this 指向是有问题的。
js
const obj = {
count : 0,
start:function(){
setInterval(function(){
this.count++;
},1000);
}
}以上的代码是达不到想要的效果的,这里就是由于 this 的指向出现了问题,因为 setInterval 的回调函数本质上是 window 在调用,也就是说 this.count 实际上是 window.count,而非 obj.count。在以前,要解决这个问题,要使用闭包,即以下手法:
js
const obj = {
count : 0,
start:function(){
const _this = this;
setInterval(function(){
_this.count++;
},1000);
}
}但是这个代码显然就不好,为了解决这个问题,ES 6 提出了箭头函数,箭头函数可以很方便地解决这个问题。
js
() => {}上面这个就是箭头函数最常规的写法,小括号里写上参数,大括号里写上语句。显然,箭头函数是没有函数名的,所以他是一个匿名函数,其实也就是函数表达式。所以理论上来说,我们的匿名函数就可以直接替换成箭头函数。
js
const obj = {
count : 0,
start:function(){
setInterval(() => {
this.count++;
},1000);
}
}我们把前面的代码修改为箭头函数,这个语句就是完全正确的。为什么呢?这就是箭头函数最神奇的地方。箭头函数中根本就没有 this 这个东西,如果我们访问箭头函数中的 this,实际上是在访问外面的 this,在上面的例子中,箭头函数中的 this 也就是 start 函数中的 this。
注意,箭头函数确实很好用,在很多时候也很方便,但是并不是所有的地方都适合用箭头函数,例如对象的属性,是非常不适合用箭头函数的。
js
const obj = {
count: 0,
print:() => {
console.log(this.count);
}
}此时调用这个 print,是无法输出正确的结果的,因为箭头函数本身并不绑定 this,他拿到的是作用域链上的 this,也就是说,它拿到的 this 其实是
js
const obj = {
a:this,
}实际上和上面这个位置的 this 是一样的,这个 this 很显然是全局对象,因为它并没有在任何函数内部。所以在这种场景下,我们不会使用箭头函数。我们常遇到的 this 指向问题更多的其实是因为在函数内部套函数出现的 this 指向问题。
实际上,箭头函数中根本不存在
this,arguments,new.target。
箭头函数实际上是可以简写的,如果只有一个参数,其实是可以省略小括号的
js
const fn = a => {
console.log(a);
}
fn(2);如果箭头函数只有一条返回语句,甚至连大括号和 return 关键字都可以省略掉
js
const fn = a => a+1;
/*
上面的代码相当于:
const fn = (a) => {
return a+1;
}
*/
console.log(2);这种简写有一个细节,就是返回对象的时候,需要将对象用小括号括起来
js
const fn1 = (a,b) => ({
a:a,
b:b
})如果不用小括号括起来,那么大括号将不会被解析为对象,而被解析为代码块,所以会直接报错。
箭头函数还有一些比较需要注意的地方,箭头函数没有原型,或者说没有 prototype 属性,所以箭头函数根本不能作为构造函数使用。
从这里我们也应该看得到,箭头函数比起普通的匿名函数少了很多的东西,所以箭头函数的应用场景也比较有限,一般来说,临时性使用的函数我们都愿意使用箭头函数,比较典型的是回调函数,比如数组方法中就有很多回调函数。实际上,只要不是我们会刻意调用的函数,都可以使用箭头函数,包括事件处理函数这种,当然,如果把箭头函数用在事件处理函数,需要注意一下 this 指向问题。除此之外,由于箭头函数没有绑定 this,所以可以拿到外层的 this,所以当我们需要拿到外层 this 的场景,我们也可以使用箭头函数。