admin管理员组

文章数量:1287219

ES6 introduced a 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();

ES6 introduced a 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 notations behave differently, as you can see. If I do new obj1.a() in the browser (tested Chrome and Firefox), I get a TypeError: obj1.a is not a constructor. new obj2.a() behaves pletely normally.

What happens here? Does anyone have an explanation, and/or links to documentation/specification?

Share Improve this question edited Dec 16, 2016 at 23:42 Michał Perłakowski 92.7k30 gold badges163 silver badges187 bronze badges asked Dec 16, 2016 at 22:08 user2345user2345 3,2271 gold badge22 silver badges43 bronze badges 2
  • methods (using method definitions in class or object literals) and arrow functions cannot be used with new. You'll have to use on old-fashioned function or a class constructor for that. – Bergi Commented Dec 17, 2016 at 13:41
  • Pre-ES6, functions and constructors were all mixed up. ES6 attempts to differentiate them. – Oriol Commented Dec 17, 2016 at 14:06
Add a ment  | 

3 Answers 3

Reset to default 12

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 bees 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.

Seems the original discussion happens here: https://github./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

Methods declared using this syntax are not intended to be constructable

Reference here

本文标签: javascriptConstructor behaving differently using ES6 shorthand notationStack Overflow