构造函数始终是函数对象

Is a constructor always a function object?

本文关键字:函数 对象 构造函数      更新时间:2023-09-26

我正在阅读最新的 ECMA-262 参考,2011 年 6 月 5.1 版。

在第 8.6.2 节表 9 中,我们有关于 [[构造]] 内部属性:

创建一个对象。 通过新运算符调用。 这 SpecOp 的参数是传递给 新运算符。实现此内部方法的对象 称为构造函数。

该标准并没有说构造函数必须是函数对象。那么我们可以有一个不是函数对象的构造函数对象吗?

根据要求链接到标准

答案非常简单。ES5 § 4.3.4 说:

Constructor Function object that creates and initialises objects.

所以你有它,根据定义,只有函数可以是构造函数。但是,可能有些主机对象的行为类似于构造函数,而构造函数不具有本机函数对象的任何其他属性(例如,在 ActiveX 中实现的 IE 中的原始 XMLHttpRequest 对象)。

虽然定义了

术语"构造函数"(如@RobG指出的那样),但没有什么可以阻止非"构造函数"对象具有[[Construct]]方法。

这有点令人困惑。这意味着您可以在不是Function的对象上使用 new 运算符(因此不是 4.3.4 中的"构造函数")),但确实提供了一种[[Construct]]方法。

请注意,没有一个标准对象符合条件,但主机对象确实可能符合条件。像Java这样的浏览器插件可能会公开一些对象,如下所示:

new java.lang.String(); // it works, so java.lang.String has a [[Construct]] method
java.lang.String instanceof Function // false
Object.prototype.toString.call(java.lang.String).indexOf('Function') // -1

请注意,即使java.lang.String不是函数,typeof java.lang.String也会返回"function"。根据 11.4.3,这是正确的(它是具有 [[Call]] 方法的主机对象)

添加到 Pumbaa80 的答案中(这对于评论来说太长了)。

混淆增加了 13.2.2,

根据该 13.2.2,当执行函数的construct时,必须执行其call操作(但它没有说明当执行不是函数的对象construct时必须做什么)。现在,根据 9.11,实现call的对象是可调用的函数对象。

同样根据 4.2 "函数是一个可调用的对象"。但当然,这并不意味着每个可调用对象都是一个函数。

因此,如果我做对了,非函数对象可以有一个Construct方法,也可以有一个Call方法。 java.lang.String就是这样一个例子。