前言
我们都知道,在ES6之前,我们定义函数都是用的最传统的function定义方式,ES6之后则支持使用箭头函数的方式去定义一个函数。对于熟知箭头函数的小伙伴们应该都会觉得箭头函数的写法很简洁与方便,当然我也是嘿嘿~
这里我先简单复习一下箭头函数的几个注意点:
1)箭头函数没有自己的this对象
2)不可以当做构造函数,也就是说,不可以对箭头函数使用new命令,否则会抛出错误
3)不可以使用arguments对象,该对象在函数体内部存在。如果要是用,可以 用rest参数代替
4)不可以使用yield命令,因此箭头函数不能用作Fenerator函数
上面的四点中,最重要的是第一点。多余普通函数来说,内部this指向函数运行时所在的对象,但是这一点对箭头函数不成立,它没有自己的this对象,内部的this就是定义时上层作用域中的this。也就是说,箭头函数内部的this指向是固定的,相比之下,普通函数的this指向是可变的。
这次我要分享的也正是箭头函数由于this指向的特殊性,其不适用的一些场合,感兴趣的朋友接着看下吧~
不适用的场合
由于箭头函数使得this从“动态”变成“静态”,下面两个场合不应该使用箭头函数。
定义对象的方法
const cat={
lives:9,
jumps:()=>{
this.lives--
}
}
上面代码中,cat.jumps()方法是一个箭头函数,这是错误的。调用cat.jumps()时,如果是普通函数,该方法内部的this指向cat;如果写成上面这样的箭头函数,使得this指向全局对象,因此不会得到预期结果。这是因为对象不够称单独的作用域,导致jumps箭头函数定义时的作用域就是全局作用域。
再看一个例子
globalThis.a =21
const obj={
a:23,
m:()=>{
console.log(this.a)
}
}
obj.m()
上面例子中,obj.m()使用箭头函数定义。JavaScript引擎的处理方式是,先在全局空间上生成这个箭头函数,然后赋值为obj.m,这法制箭头函数的内部this指向全局对象,所以obj.m()输出的是全局空间的21,而不是内部对象额23,。上面的代码实际上等同于下面的代码:
globalThis.a =21
globalThis.m=()=>{
console.log(this.a)
}
const obj={
a:23,
m:globalThis.m
}
obj.m()
由于上面这个原因,对象的属性建议使用传统的写法定义,不要使用箭头函数定义。
动态绑定this
var button =document.getElementById('button')
button.addEventListener('click',()=>{
this.classList.toggle('on')
})
上面代码运行时,点击按钮会报错。因为button的监听函数是一个箭头函数,导致里面的this就是全局对象。如果改成普通函数,this就会动态指向被点击的按钮对象。
另外,如果函数体很复杂,有许多行,或者函数内部有大量的读写操作,不单纯是为了计算值,这时也不应该使用箭头函数,而是使用普通函数,这样可以提高代码可读性。