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

cpc*_*len 4 javascript constructor function language-lawyer

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

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

一些 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: {}}));
Run Code Online (Sandbox Code Playgroud)

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

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

Mic*_*yck 5

重述:对象 X 是否有可能返回truefor IsConstructor(X)but falsefor IsCallable(X)?即,对象 X 是否有可能具有[[Construct]]内部方法但没有[[Call]]内部方法?

ECMAScript 规范在这一点上并不像它可能的那样明确。

(1) 6.1.7.2“对象内部方法和内部槽”说:

函数对象是支持[[呼叫]]内部方法的对象。甲构造(也被称为一个构造函数)是一个函数对象支持[[构建]]内部方法。

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

(2) 请注意,在定义 的子句中IsConstructor,序言说它确定其参数是否“是具有 [[Construct]] 内部方法的函数对象”,但该算法没有明确检查该参数是否为一个函数对象。这表明(规范编写者认为)具有 [[Construct]] 内部方法足以保证参数是函数对象,即它具有 [[Call]] 内部方法。

(3)仅指向具有[[Construct]]内部方法是调用它在所述Construct抽象操作。与第 (2) 点类似,序言说该操作“用于调用函数对象的 [[Construct]] 内部方法”,但该算法并未明确检查它F是否是函数对象。

所以我相信答案是,虽然规范没有明确说这样的对象不能存在,但它相当强烈地暗示/假设它们不存在。


更新(2018-05-22):

6.1.7.2 “对象内部方法和内部插槽”现在已修改为(强调我的):

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