ES6引入了一个shorthand notation来初始化具有函数和属性的对象.
// 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();
但是,正如您所看到的,这些不同的符号表现不同.如果我在浏览器中做了新的obj1.a()(测试过Chrome和Firefox),我会得到一个TypeError:obj1.a不是构造函数. new obj2.a()表现完全正常.
这里发生了什么?有没有人有解释,和/或文档/规范的链接?
解决方法:
specification对解释这个问题不是很直接,但我们可以遵循一个短链..
我们将从EvaluateNew开始,因为这是我们想知道的行为.第7步显然是我们在这里寻找的那个:
- If IsConstructor(constructor) is false, throw a TypeError exception.
所以IsConstructor是我们下一步要看的地方.
摘要和步骤都描述了这一点:
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.
因此,根据它的外观来判断,我们的obj1.a没有[[Construct]]内部方法.让我们来看看它不应该有一个……
这是我们正在寻找的东西,PropertyDefinitionEvaluation.第一步在这里很有用:
Let methodDef be DefineMethod of MethodDefinition with argument object.
只用一个参数,即对象来调用DefineMethod.让我们看一下DefineMethod – 这就是我们需要的:
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]).
由于functionPrototype未作为参数传递,因此类型为Method.让我们来看看FunctionCreate的用途:
- If kind is not
Normal
, let allocKind be"non-constructor"
.- Else, let allocKind be
"normal"
.- Let F be FunctionAllocate([other arguments snipped], allocKind).
现在我们越来越近了!我们只需要看一下FunctionAllocate与allocKind(根据上面的步骤是“非构造函数”),这就是函数所有内部方法等等.
- 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 07007. 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"
.
最后!如果我们通过相关步骤,我们可以看到,因为functionKind不是“正常”,needsConstruct变为false,所以永远不会分配[[Construct]]内部方法!然后IsConstructor看到并返回false,因此EvaluateNew失败.
MDN非常简单地描述了这种行为:
All method definitions are not constructors and will throw a TypeError if you try to instantiate them.
..但是现在你们知道他们不是正式的建造者.