是否存在IsCallable为false但IsConstructor为true的JS对象?

时间:2018-04-30 23:33:00

标签: javascript function constructor language-lawyer

如果ECMAScript规范函数IsCallable的参数具有[[Call]]内部方法,则返回true。它在规范中的几个地方使用,例如Array.prototype.toString的定义。

有一个类似的规范函数IsConstructor,如果它的参数有一个[[Construct]]内部方法,则返回true。

一些JS对象,包括大多数内置函数,如escape,都是可调用的,但不可构造。 是否有可构造但不可赎回的内容?

请注意,用户定义的类和内置类在作为普通函数调用时抛出TypeError,但仍可根据IsCallable的定义调用,可以通过查看Array.prototype.toString是否会尝试来确定将它们用作join

的实现

// {} is not callable, so toString falls back to Object.prototype.toString:
console.log('null:', Array.prototype.toString.apply({join: {}}));

// WeakMap is callable (but throws TypeError):
console.log('null:', Array.prototype.toString.apply({join: WeakMap}));

// User-defined classes also callable:
console.log('null:', Array.prototype.toString.apply({join: class Foo {}}));

2 个答案:

答案 0 :(得分:3)

重述:对象X是否可以为true返回IsConstructor(X),而为false返回IsCallable(X)?即,对象X是否可以使用[[Construct]]内部方法但是没有[[Call]]内部方法?

ECMAScript规范并不像这一点那样明确。

(1) 6.1.7.2 "Object Internal Methods and Internal Slots"说:

  

函数对象是一个支持[[Call]]内部方法的对象。 构造函数(也称为构造函数)是一个支持[[Construct]]内部方法的函数对象。

由此我们可以得出结论,如果存在这样的对象X ,那么它显然不是一个'功能对象'因此也不是“构造函数”。即对于不被视为“构造函数”的对象,IsConstuctor(X)会返回true,这将是奇怪的。

(2) 请注意,在定义IsConstructor的子句中,前导码表示它确定其参数"是否是具有[[Construct]]内部方法"的函数对象,但算法不是t明确检查参数是否为函数对象。这表明(规范作者认为)具有[[Construct]]内部方法足以保证参数是一个函数对象,即它具有[[Call]]内部方法。

(3) 拥有[[Construct]]内部方法的唯一要点是在the Construct abstract operation中调用它。与点(2)类似,前导码表示操作"用于调用函数对象的[[Construct]]内部方法",但算法没有明确检查{{ 1}}是一个函数对象。

所以我相信答案是,虽然规范并没有明确说这些对象不存在,但它强烈暗示/假设他们不会这样做。吨。

更新(2018-05-22):

6.1.7.2 "Object Internal Methods and Internal Slots"现在已被修改为(强调我的):

  

函数对象是一个支持[[Call]]内部方法的对象。 构造函数是一个支持[[Construct]]内部方法的对象。 支持[[Construct]]的每个对象都必须支持[[Call]] ;也就是说,每个构造函数都必须是一个函数对象。因此,构造函数也可以称为构造函数构造函数对象

答案 1 :(得分:2)

不,不可能创建可构造但不可调用的东西。在规范中定义[[Construct]]的所有东西都是除了代理之外的函数,代理只有[[Construct]],而它们的目标也是(9.15.4)。

  

如果[[ProxyTarget]]内部插槽的初始值是具有[[Construct]]内部方法的对象,则代理异类对象只有[[Construct]]内部方法。