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)
重述:对象 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]];也就是说,每个构造函数都必须是一个函数对象。因此,构造函数也可以称为构造函数或构造函数对象。