this在箭头函数中的使用及什么场景下不能使用箭头函数?
箭头函数的诞生,可以说给我们的工作带来了极大的便利,箭头函数很高级,可以规避this的问题,但有些场景却是不能使用箭头函数的,这些你都了解过吗?
一、箭头函数缺点
1、没有arguments,如果要用,可以用rest参数代替
const fn1 = () => { console.log('arguments',arguments) } fn1(1,2) // 报错:Uncaught ReferenceError: arguments is not defined function fn2(){ console.log('arguments',arguments) } fn2(1,2) // Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ] const fn3 = (...values) => { console.log('values',values) } fn3(1,2) // [1, 2]
2、无法通过apply、call、bind改变this指向(箭头函数的this就是它父容器的this,不是在执行的时候确定的,而是在定义的时候确定的)
const fn3 = () => { console.log('this',this) } fn3() // Window fn3.call({x:1}) // Window function fn4(){ console.log('this',this) } fn4() // Window fn4.call({x:1}) // {x:1}
如上图代码,我们可以发现,箭头函数的两次执行的this都是指向了Window,使用call并没有发生改变,而普通函数第一次是指向了Window,第二次则是变成了我们传入的
二、不能使用箭头函数的情况
1、对象方法中,不适用箭头函数
const obj = { name: '张三', getName() { return this.name }, getName1: () => { return this.name } } console.log('普通函数',obj.getName()) // 张三 console.log('箭头函数',obj.getName1()) // 未获取到值
为什么对象方法中,箭头函数的this指向不是这个对象?
A、this永远指向函数的调用者
B、在箭头函数中,this指向的是定义时所在的对象,而不是使用时所在的对象。换句话说,箭头函数没有自己的this,而是继承父作用域中的this
2、原型方法中,不适用箭头函数
const obj = { name:'张三' } obj.__proto__.getName = function() { return this.name } obj.__proto__getName1 = () => { return this.name } console.log(obj.getName()) // 张三 console.log(obj.getName1()) // 未获取到值
出现问题的原因是this指向Window对象,这和使用箭头函数在对象中定义方法十分类似
3、构造函数中,不适用箭头函数
function Foo(name,sex) { this.name = name this.sex = sex } const Foo1 = (name,sex) => { this.name = name this.sex = sex } console.log('普通的构造函数',new Foo('张三','男')) // Foo {name: '张三', sex: '男'} console.log('箭头函数',new Foo1('张三','男')) // Uncaught TypeError: Foo1 is not a constructor
构造函数是通过new关键字来生成对象实例的,生成对象实例的过程也是通过构造函数给实例绑定this的过程,而箭头函数没有自己的this。因此不能使用箭头函数作为构造函数,也就不能通过new操作符来调用箭头函数
4、动态上下文中的回调函数,不适用箭头函数
const btn1 = document.getElementById('btn1') btn1.addEventListener('click',() => { this.innerHTML = 'clicked' })
如果我们在回调函数中不需要使用到this,那就没啥问题了,但是,使用到了就有问题了。箭头函数的this指向的是它的父作用域(这里就指向Window),而不是指向这个button,这时候我们需要使用普通函数才可以
5、Vue生命周期和method中,不适用箭头函数
{ data(){ return { name:'张三' } }, methods:{ getName() { return this.name // 正常 }, getName1: () => { return this.name // 报错:Cannot read properties of undefined (reading 'name') } }, // mounted() { // console.log('name',this.name) // 正常,张三 // }, mounted: () => { console.log('name',this.name) // 报错:Cannot read properties of undefined (reading 'name') } }
Vue本质上是一个JS对象,我们上面讲过对象方法中,不适用箭头函数。它的本质上和对象方法中,不适用箭头函数是一样的。
既然Vue不行,作为热门框架之一的React行吗?
emmmm......还真的可以
因为React组件(非Hooks)本质上是一个ES6的class,我们可以试试
class Man { constructor(name,city){ this.name = name this.city = city } getName = () => { return this.name } } const f = new Man('张三','广州') console.log(f.getName()) // 张三