0
点赞
收藏
分享

微信扫一扫

【捣鼓】TypeError: “x” is not a constructor

IT程序员 2022-04-23 阅读 52

今天在处理一个问题的时候无意中发现一个新的问题,对象内的简写方法不能用作构造函数使用,而属性赋值的匿名函数可以。

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]]是我们使用newsuper创建新对象时使用的东西,

只有类型的函数 Normal才能构造和实现[[Construct]]

所以,只有 Normal 类型的函数(也就是用 function 关键字构造的函数)是可作为构造器使用的,
其他类型的函数(箭头函数、方法简写,generator)都无法使用构造器,也就是说,不能用 new 操作符调用。


MDN: TypeError: “x” is not a constructor


原文链接

阅读规范会发现 JavaScript 对象具有定义其特定行为的内部方法。

有“基本的内部方法”,范围从例如[[GetPrototypeOf]][[OwnPropertyKeys]].

当我们处理函数时(记住这些也是对象),还可以有“附加的基本内部方法”,其中包括[[Call]][[Construct]][[Construct]]是我们使用newsuper创建新对象时使用的东西。

事实证明,并非每个函数都包含[[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。这导致它们成为“非构造函数”。


举报

相关推荐

0 条评论