Constructor behaves differently using the abbreviation ES6

ES6 introduced shorthand notation to initialize objects with functions and properties.

// ES6 shorthand notation const obj1 = { a(b) { console.log("ES6: obj1"); } }; // ES5 var obj2 = { a: function a(b) { console.log("ES5: obj2"); } }; obj2.a(); obj1.a(); new obj2.a(); new obj1.a(); 

However, these different designations behave differently, as you can see. If I do new obj1.a() in the browser (tested by Chrome and Firefox), I get TypeError: obj1.a is not a constructor . new obj2.a() behaves normally.

What's going on here? Does anyone have an explanation and / or links to documentation / specification?

+8
javascript methods ecmascript-6
Dec 16 '16 at 22:08
source share
2 answers

the specification doesnโ€™t explain this very directly, but we can follow a short chain.

We will start with EvaluateNew , as we are interested in this behavior. Step 7 is definitely the one we are looking for here:

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

So IsConstructor is where we need to look further.

Both summaries and steps describe this:

The IsConstructor abstract operation determines whether the argument, which should be an ECMAScript language value, is a functional object with an internal method [[Construct]].




  • If the type (argument) is not an object, return false .
  • If the argument has an internal [[Construct]] method, return true .
  • Returns false .

So, judging by the appearance, our obj1.a does not have an internal method [[Construct]]. Let's see where it says that he should not have one.

Here we are looking for PropertyDefinitionEvaluation . The first step is useful here:

Let methodDef be DefineMethod of MethodDefinition with an argument object.

This calls DefineMethod with only one argument, an object. Let's look at DefineMethod - this is what we need:

With the object parameter and optional functionPrototype parameter.




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

Since functionPrototype was not passed as a parameter, the Method view. Let's see what FunctionCreate does with this:

  1. If the type is not Normal , let allocKind be "non-constructor" .
  2. Otherwise, let allocKind be "normal" .
  3. Let F be the function Allocate ([other arguments snipped], allocKind).

Now we are getting closer! We just need to look at FunctionAllocate with allocKind (which is equal to "non-constructor" in accordance with the steps above), which gives the functions of all its internal methods, etc.

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


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


      1. If requireConstruct true , then

        but. Set the internal method F [[Construct]] to the definition specified in 9.2.2.

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

At last! If we go through the appropriate steps, we will see, since functionKind is not "normal" , needsConstruct becomes false , and so the internal [[Construct]] method is never assigned! Then IsConstructor sees this and returns false, and therefore EvaluateNew fails.

MDN describes this behavior very simply:

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

.. but now you know how they are not constructors, officially.

+4
Dec 17 '16 at 13:34
source share

Methods declared using this syntax are not intended to be constructed.

Link here

+1
Dec 16 '16 at
source share



All Articles