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