Constructor behaving differently using ES6 shorthand notation

落花浮王杯 提交于 2019-11-27 22:21:46
Florrie

The specification isn't very direct about explaining this, but we can follow a short chain..

We'll start at EvaluateNew, since that's the behaviour we're wondering about. Step 7 is clearly the one we're looking for here:

  1. If IsConstructor(constructor) is false, throw a TypeError exception.

So IsConstructor is where we need to look next.

Both the summary and the steps describe this:

The abstract operation IsConstructor determines if argument, which must be an ECMAScript language value, is a function object with a [[Construct]] internal method.


  1. If Type(argument) is not Object, return false.
  2. If argument has a [[Construct]] internal method, return true.
  3. Return false.

So, judging by the looks of it, our obj1.a doesn't have a [[Construct]] internal method. Let's look for where it says that it shouldn't have one..

Here's what we're looking for, PropertyDefinitionEvaluation. The first step is useful here:

Let methodDef be DefineMethod of MethodDefinition with argument object.

That calls DefineMethod with just one argument, object. Let's look at DefineMethod - here's what we need:

With parameters object and optional parameter functionPrototype.


  1. If functionPrototype was passed as a parameter, let kind be Normal; otherwise let kind be Method.
  2. Let closure be FunctionCreate(kind, [more arguments snipped]).

Since functionPrototype was not passed as a parameter, the kind is Method. Let's look at what FunctionCreate does with that:

  1. If kind is not Normal, let allocKind be "non-constructor".
  2. Else, let allocKind be "normal".
  3. Let F be FunctionAllocate([other arguments snipped], allocKind).

Now we're getting close! We just need to look at FunctionAllocate does with allocKind (which is "non-constructor" as per the above steps), which is what gives a function all of its internal methods and such.

  1. If functionKind is "normal", let needsConstruct be true.
  2. Else, let needsConstruct be false.

  1. Let F be a newly created ECMAScript function object with the internal slots listed in Table 27. All of those internal slots are initialized to undefined.

  1. If needsConstruct is true, then

    a. Set F's [[Construct]] internal method to the definition specified in 9.2.2.

    b. Set the [[ConstructorKind]] internal slot of F to "base".

Finally! If we go through the relevant steps, we can see since functionKind isn't "normal", needsConstruct becomes false, and so a [[Construct]] internal method is never assigned! Then IsConstructor sees that and returns false, and so EvaluateNew fails.

MDN describes this behaviour very simply:

All method definitions are not constructors and will throw a TypeError if you try to instantiate them.

..but now you know how they aren't constructors, officially.

Methods declared using this syntax are not intended to be constructable

Reference here

Seems the original discussion happens here: https://github.com/rwaldron/tc39-notes/blob/master/es6/2012-07/july-26.md

MM: three reasons for this:

  • precedent in builtins
  • using a method as a constructor is generally nonsense
  • to freeze a class, I have to freeze the .prototype of the methods on the prototype!!

and

AWB: suggestion: concise methods should be the same for both classes and object literals

  • strictness
  • enumerability
  • constructability
  • attributes

That's how both class methods and object methods became non-constructable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!