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:
- 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.
- If functionPrototype was passed as a parameter, let kind be
Normal ; otherwise let kind be Method . - 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:
- If the type is not
Normal , let allocKind be "non-constructor" . - Otherwise, let allocKind be
"normal" . - 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.
- If functionKind is
"normal" , let needsConstruct be true . - Otherwise, let needsConstruct be false .
- 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 .
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.