今天在处理一个问题的时候无意中发现一个新的问题,对象内的简写方法不能用作构造函数使用,而属性赋值的匿名函数可以。
const obj1 = {
f:function () {
this.num = 0;
}
}
const obj2 = {
f() {
this.num = 0;
}
}
new obj1.f(); // f {num: 0}
new obj2.f(); // Uncaught TypeError: obj2.f is not a constructor
为此专门去和同学讨论和搜索了一下,后面放上是相关链接的 google 机翻,
总的结果就是,
未标识为构造函数的内置函数对象不实现 [[Construct]] 内部方法,
[[Construct]]是我们使用new或super创建新对象时使用的东西,
只有类型的函数 Normal才能构造和实现[[Construct]]。
所以,只有 Normal 类型的函数(也就是用 function 关键字构造的函数)是可作为构造器使用的,
其他类型的函数(箭头函数、方法简写,generator)都无法使用构造器,也就是说,不能用 new 操作符调用。
MDN: TypeError: “x” is not a constructor
原文链接
阅读规范会发现 JavaScript 对象具有定义其特定行为的内部方法。
有“基本的内部方法”,范围从例如[[GetPrototypeOf]]到[[OwnPropertyKeys]].
当我们处理函数时(记住这些也是对象),还可以有“附加的基本内部方法”,其中包括[[Call]]和[[Construct]]。[[Construct]]是我们使用new或super创建新对象时使用的东西。
事实证明,并非每个函数都包含[[Construct]],这意味着并非每个函数都是构造函数。
查看操作的定义,new我们会看到它应该在TypeError任何时候抛出一个isConstructor错误。isContructor查找[[Construct]]内部方法。
那么,让我们看看下面的三行代码,看看当我们想要使用 函数 Fn Arrow Shorthand作为构造函数时会发生什么:
const example = {
Fn: function() { console.log(this); },
Arrow: () => { console.log(this); },
Shorthand() { console.log(this); }
};
new example.Fn(); // Fn {}
new example.Arrow(); // Uncaught TypeError: example.Arrow is not a constructor
new example.Shorthand(); // Uncaught TypeError: example.Shorthand is not a constructor
每个函数创建的定义都归结为FunctionCreateEcmaScript 规范中的定义。
规格FunctionCreate非常明确:
FunctionCreate
所以事实证明,只有类型的函数Normal才能构造和实现[[Construct]]。进一步阅读规范,您会发现箭头函数使用 kindArrow而方法简写定义使用 kind Method。这导致它们成为“非构造函数”。
