The specification does not provide clear guidance on this topic, but we can follow a concise sequence of steps.
We will begin at EvaluateNew, as that is where the behavior in question lies. Step 7 directly addresses our query:
- If IsConstructor(constructor) returns false, then a TypeError exception is thrown.
Next, we need to investigate the function IsConstructor.
Both the overview and the detailed steps shed light on this concept:
The operation IsConstructor determines whether the provided argument, an ECMAScript value, is a function object with a [[Construct]] internal method.
- If Type(argument) is not Object, return false.
- If argument has a [[Construct]] internal method, return true.
- Otherwise, return false.
Based on this explanation, it seems like our obj1.a
lacks a [[Construct]] internal method. Let's pinpoint where this specification is mentioned.
The relevant section to look into now is PropertyDefinitionEvaluation. The initial step holds a clue:
Invoke DefineMethod from MethodDefinition using argument object.
Calling DefineMethod with just one parameter, object, offers further insight:
Taking object parameters and optional functionPrototype arguments.
- If functionPrototype is present, consider the kind as
Normal
; otherwise, treat it as Method
.
- Create a closure using FunctionCreate based on the determined kind.
In the absence of functionPrototype as an argument, the kind defaults to Method
. Exploring how FunctionCreate handles this revelation is crucial:
- If the kind is not
Normal
, set allocation type as "non-constructor"
.
- Otherwise, designate the allocation type as
"normal"
.
- Use FunctionAllocate, considering allocKind parameters, to allocate F accordingly.
This brings us closer to understanding the process. By examining FunctionAllocate in-depth, specifically its handling of allocKind (in this case, "non-constructor"
), we unearth details about a function's intrinsic methods.
- If the functionKind is
"normal"
, ensure needsConstruct is set to true.
- Otherwise, specify needsConstruct as false.
- Create an ECMAScript function object F with predefined internal slots as outlined in Table 27, initializing all slots to undefined.
If needsConstruct is true, then
a. Implement F's [[Construct]] internal method per the definition in section 9.2.2.
b. Assign "base"
to the [[ConstructorKind]] slot of F.
Following these fundamentals, we observe that since the functionKind is not "normal"
, needsConstruct resolves to false, resulting in the lack of a [[Construct]] internal method assignment. Subsequently, IsConstructor identifies this and returns false, leading to the failure of EvaluateNew.
MDN succinctly summarizes this notion:
All method definitions are non-constructors and attempting to instantiate them will raise a TypeError.
Now armed with this knowledge, you understand the official reasoning behind why such methods do not qualify as constructors.