箭头函数也有不好用的时候

122 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

 // 问:下面的console.log输出什么?
 let arrowFunction = () => {};
  console.log(new arrowFunction());

几年前当我第一次被问到这个问题的时候,我意思到哪里不对劲,但是时间紧迫,面试官追问我输出什么,是输出对象吗?很犹豫。。。那就是吧。一个小时以后当面试一结束。。思考片刻我突然意识我翻车了。。。

1657530446705.png

从头来想这个问题。首先 new一个对象做什么?

  • 创建一个全新的对象
  • 这个新对象会被执行原型连接
  • 这个新对象会绑定到函数调用的 this
  • 如果函数没有返回其它对象,那么 new 表达式种的函数调用会自动返回这个新对象

我们可以看到 new 的操作中就有 this 的绑定,我们在来看看代码。

1657618222068.png

这里在实现一个new 方法,更好的理解

function myNew(consturctor,...argas){
    //创建一个全新的对象,这个新对象会被执行原型连接,及继承 constructor 的原型
    const obj = object.create(constructor.protype);
    //这个新对象会绑定到函数调用的 `this`,及将 obj 作为 this ,执行 constructor ,传入参数
    constructor.apply(obj.args);
    //返回 obj
    return obj
}

那么在来说下 this,通常情况下this 要在执行时确认,定义时无法确认.

  • 作为构造函数执行
  • 作为对象属性执行
  • 作为普通函数执行
  • call apply bind 可以改变 this指向
let a = {
    name:'A',
    fn: function () {
        console.log(this)
    }
}
console.log(a.fn())
console.log(a.fn.call({name:'B'}))
let fn1= a.fn;
console.log(fn1())

1657693329615.png

总结:通常情况下,函数的this 要在执行时确认,定义时无法确认,也就是谁引用它,this就指向谁

但是当我们将函数变成箭头函数的时候情况发生了变化。

let a = {
    name:'A',
    fn: () => {
        console.log(this)
    }
}
console.log(a.fn())
console.log(a.fn.call({name:'B'}))
let fn1= a.fn;
console.log(fn1())

1657693480490.png

对于普通函数来说,内部的this指向函数运行时所在的对象,但是这一点对箭头函数不成立。它没有自己的this对象,内部的this就是定义时上层作用域中的this。也就是说,箭头函数内部的this指向是固定的,call apply bind 不可以改变 this指向。相比之下,普通函数的this指向是可变的。同时箭头函数不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

总结:

箭头函数存在着许多不适用的场景

  • 不适合当作构造函数,也就是说,不可以对箭头函数使用new命令,否则会抛出一个错误。
  • 不适合作为对象的方法
  • 不适合作为扩展对象原型
  • 不适合动态上下文中的回调函数
  • 因Vue组件是一个对象,所以不适合作为Vue生命周期和方法

PS: Object.create 可以指定原型,创建一个空对象。
{} 就相当于 Object.create(Object.prototype) ,即根据 Object 原型的空对象。