Javascript ES6, why I can not use `new` with arrow

2020-02-08 21:10发布

问题:

As far as I know, arrow function is similar to normal function. There is no problem when I use like this:

let X = () => {};
let Y = function() {};
X();
Y();

However, error occurred when I use them with new

let X = () => {};
let Y = function() {};
x = new X();
y = new Y();

Uncaught TypeError: X is not a constructor

Would you please explain me why? Many thanks.

回答1:

You may wish to clarify your question.

Q. What did I do wrong?

A. You used new with an arrow function, and that's not allowed.

Q. Can I turn an arrow function into a constructor?

A. Only by wrapping it in a normal function, which would be silly. You can't turn an arrow function itself into a constructor.

Q. Can you explain how the specification disallows new with arrow functions?

A. To be a constructor, a function object must have a [[Construct]] internal method.

Functions created with the function keyword are constructors, as are some built-in functions such as Date. These are the functions you can use with new.

Other function objects do not have a [[Construct]] internal method. These include arrow functions. So you can't use new with these. This makes sense since you can't set the this value of an arrow function.

Some built-in functions are also not constructors. E.g. you can't do new parseInt().

Q. Can you explain the rationale behind disallowing new with arrow functions in the specification?

A. Use common sense, or search the es-discuss archives.



回答2:

Arrow functions are not synonymous with normal functions. arguments and this inside arrow functions reference their outer function.

When the code new Foo(...) is executed, the following things happen:

  1. A new object is created, inheriting from Foo.prototype.
  2. The constructor function Foo is called with the specified arguments, and with this bound to the newly created object. new Foo is equivalent to new Foo(), i.e. if no argument list is specified, Foo is called without arguments.
  3. The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)

Since this inside an arrow function references its outer function (arrow functions inherit this from their declaration context, as @Iven is saying), using new keyword with an arrow function does not really make sense.