js箭头函数三问

195 阅读2分钟

1、箭头函数为什么不能被new

2、箭头函数的this绑定为什么无法被修改?

3、有什么办法可以修改箭头函数的this指向绑定?

1.箭头函数没有构造函数

来看下面这个例子

new (() => {})
Uncaught TypeError: (intermediate value) is not a constructor
  at <anonymous>:1:1

JS中,构造函数只是使用new操作符时被调用的普通函数,他们不属于某个类,也不会实例化一个类。

而箭头函数没有name属性,也并非通过function等方式定义,而new操作符在构造在执行构造的时候,在编译过程,词法解析中会将后面的函数作为构造函数使用,而箭头函数 () = >{} 会被词法解析识别,当做大型块作用域来处理(所有代码在为编译阶段都是一堆字符串)

下面是new的简单实现:

function create () {  
// 1.创建一个空对象, new Object方式创建的比较纯净,只有Object.prototype继承
  let obj = new Object();
  // 2.new 后面的构造函数会作为第一个参数传递进new函数,通过获取arguments第一次参数方式获取
  const Con = [].shift.call(arguments); 
 // 3.新对象的原型指向构造函数的原型 
 obj.__proto__ = Con.prototype;
  // 4.指向构造函数,如果构造函数执行后有返回值,则返回函数执行后的返回值,如果没有则以当前新对象obj作为返回值
 var ret = Con.apply(obj, arguments);
 return ret instanceof Object ? ret : obj;
}

2.箭头函数根据外层作用域(词法作用域)来决定this,而不是本身的this

以下是[木易杨](https://muyiy.cn/blog/3/3.2.html#%E9%A2%98%E7%9B%AE1)大佬关于箭头函数this指向的总结:

  1. 箭头函数不绑定this,箭头函数中的this相当于普通变量。

  2. 箭头函数的this寻值行为与普通变量相同,在作用域中逐级寻找。

  3. 箭头函数的this无法通过bind,call,apply来直接修改(可以间接修改)。

  4. 改变作用域中this的指向可以改变箭头函数的this。

结合以上,如果把箭头函数产生的作用域当成块级作用域,是否能帮助我们快速的理解上面结论呢?

3.箭头函数可以通过修改上级作用域的方式来间接修改。

上面结论说过,箭头函数的this寻值行为与普通变量相同,在作用域中逐级寻找,那么只要通过修改上级作用域的方式就可以间接修改了。

   var person1 = {  name: 'person1',
  show: function () {
    return () => console.log(this.name)
  }
}
var person2 = { name: 'person2' }
person1.show().call(person2) // person1 person1.show.call(person2)() // person2

写文章的目的目前主要是作为学习的总结,通过输出的方式来加强自己对知识点的理解,路过的掘友,鄙人写的不好的地方请轻喷,如果能指出需要修改的地方那就再好不过了。要是懒得吐槽,那就当乐子