为什么 ArrowFunction 不能 new
文章目录
0x00 TL;DR
因为 Lexical this
导致没有 [[Construct]]
,所以不能 new
。
0x01 详细版本
如果去查一下 ECMA spec,其实可以看到如下的解释:
A function object is an object that supports the [[Call]]
internal method. A constructor is an object that supports the [[Construct]]
internal method. Every object that supports [[Construct]]
must support [[Call]]
; that is, every constructor must be a function object. Therefore, a constructor may also be referred to as a constructor function or constructor function object.
所以想要对某个对象使用 new
,就得确保该对象具有 [[Construct]]
这个内部方法。而 ArrowFunction
没有 [[Construct]]
。
再多查一点的话,可以在 14.2.17 这一节看到如下的注解:
An ArrowFunction
does not define local bindings for arguments
, super
, this
, or new.target
. Any reference to arguments
, super
, this
, or new.target
within an ArrowFunction
must resolve to a binding in a lexically enclosing environment.
再多查一点的话,可以找到最终通过的 proposal:https://tc39wiki.calculist.org/es6/arrow-functions/
The goal of Arrow Functions is to address and resolve several common pain points of traditional Function Expression:
- Lexical
this
binding;- Shorter syntactical form (
() => {}
vs.function () {}
)Lexical
this
matches the dominant cohort measured by Kevin Smith (see the BTF Measurements thread that either does not usethis
or wants it lexically bound.
- Best results after modifying subject code to use method definition shorthand and only then scanning for function.
- From lexical
this
it follows that arrow functions are not constructors (no.prototype
or[[Construct]]
).
再多查一点的话,你可以在 2011 年的一次讨论里找到这个设计的来源:https://mail.mozilla.org/pipermail/es-discuss/2012-March/021953.html
We do not want to delegate to a target function that can
[[Construct]]
, because there is no such target function -- we're not trying to sugar.bind
on a full function. That is too expensive and general (no pre-args, no full function under the hood).Lexical-only
this
binding means no[[Construct]]
and no.prototype
for arrow functions. I'm ok with this.
考虑典型的代码如下:
1 | class A { |
在这两种构造实例的方法中,this
指向的都是正在被操作的变量 a
。 但是 arrow function 在还是个草案的时候就只计划支持 Lexical this
,因此它的函数体中的 this
不会指向正在被操作的变量 a
,无法修改赋值表达式的左值,因此就算 ArrowFunction
有 [[Construct]]
内部方法也无法用于构造新对象。