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-fashionedfunction
or aclass
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
3 Answers
Reset to default 12The 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:
- 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.
- If Type(argument) is not Object, return false.
- If argument has a [[Construct]] internal method, return true.
- 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.
- If functionPrototype was passed as a parameter, let kind be
Normal
; otherwise let kind beMethod
.- 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:
- If kind is not
Normal
, let allocKind be"non-constructor"
.- Else, let allocKind be
"normal"
.- 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.
- If functionKind is
"normal"
, let needsConstruct be true.- Else, let needsConstruct be false.
- 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.
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
版权声明:本文标题:javascript - Constructor behaving differently using ES6 shorthand notation - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741305382a2371336.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论