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();
但是,正如您所看到的,这些不同的符号表现不同。如果我在浏览器中测试new obj1.a()
(经过测试的Chrome和Firefox),我会得到一个TypeError: obj1.a is not a constructor
。 new obj2.a()
表现完全正常。
这里发生了什么?有没有人有解释,和/或文档/规范的链接?
specification对解释这个并不是很直接,但我们可以遵循一个短链..
我们将从EvaluateNew开始,因为这是我们想知道的行为。第7步显然是我们在这里寻找的那个:
- 如果IsConstructor(构造函数)为false,则抛出TypeError异常。
所以IsConstructor是我们接下来要看的地方。
摘要和步骤都描述了这一点:
抽象操作IsConstructor确定参数(必须是ECMAScript语言值)是否是具有[[Construct]]内部方法的函数对象。
- 如果Type(参数)不是Object,则返回false。
- 如果参数有[[Construct]]内部方法,则返回true。
- 返回false。
因此,从它的外观来看,我们的obj1.a
没有[[Construct]]内部方法。让我们来看看它不应该有一个......
这是我们正在寻找的,PropertyDefinitionEvaluation。第一步在这里很有用:
让methodDef成为MethodDefinition的DefineMethod with argument object。
这就是DefineMethod只用一个参数,对象。让我们看一下DefineMethod - 这就是我们需要的:
带参数对象和可选参数functionPrototype。
- 如果functionPrototype作为参数传递,请将类型设为
Normal
;否则,请善待Method
。- 让闭包为FunctionCreate(kind,[更多参数剪断])。
由于functionPrototype未作为参数传递,因此类型为Method
。让我们来看看FunctionCreate对此的看法:
- 如果善良不是
Normal
,让allocKind成为"non-constructor"
。- 另外,让allocKind成为
"normal"
。- 设F为FunctionAllocate([其他参数剪切],allocKind)。
现在我们越来越近了!我们只需要看一下FunctionAllocate对allocKind的作用(按照上面的步骤就是"non-constructor"
),这就是函数的所有内部方法等等。
- 如果functionKind是
"normal"
,请让needsConstruct为true。- 否则,让needsConstruct为假。
- 设F是新创建的ECMAScript函数对象,其中内部插槽列在Table 27中。所有这些内部插槽都初始化为未定义。
- 如果needsConstruct为true,那么 一个。将F的[[Construct]]内部方法设置为9.2.2中指定的定义。 湾将F的[[ConstructorKind]]内部插槽设置为
"base"
。
最后!如果我们通过相关步骤,我们可以看到,因为functionKind不是"normal"
,needsConstruct变为false,所以永远不会分配[[Construct]]内部方法!然后IsConstructor看到并返回false,因此EvaluateNew失败。
MDN非常简单地描述了这种行为:
所有方法定义都不是构造函数,如果您尝试实例化它们,则会抛出TypeError。
..但是现在你们知道他们不是正式的建造者。
使用此语法声明的方法不可构造
似乎最初的讨论发生在这里:https://github.com/rwaldron/tc39-notes/blob/master/es6/2012-07/july-26.md
MM:三个原因:
- 内在的先例
- 使用方法作为构造函数通常是无稽之谈
- 要冻结一个类,我必须冻结原型上方法的.prototype!
和
AWB:建议:对于类和对象文字,简明的方法应该是相同的
- 严格
- enumerability
- 施工性
- 属性
这就是类方法和对象方法变得不可构造的方式