最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Are there any JS objects for which IsCallable is false but IsConstructor is true? - Stack Overflow

programmeradmin0浏览0评论

The ECMAScript specification function IsCallable returns true iff its argument has a [[Call]] internal method. It is used in several places in the specification, such as in the definition of Array.prototype.toString.

There is a similar specification function IsConstructor which returns true iff its argument has a [[Construct]] internal method.

Some JS objects, including most built-in functions such as escape are callable but not constructible. Are there any which are constructible but not callable?

Note that both user-defined and built-in classes throw TypeError when called as ordinary functions, but are still callable per the definition of IsCallable, as can be determined by seeing if Array.prototype.toString will attempt to use them as the implementation of join:

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

The ECMAScript specification function IsCallable returns true iff its argument has a [[Call]] internal method. It is used in several places in the specification, such as in the definition of Array.prototype.toString.

There is a similar specification function IsConstructor which returns true iff its argument has a [[Construct]] internal method.

Some JS objects, including most built-in functions such as escape are callable but not constructible. Are there any which are constructible but not callable?

Note that both user-defined and built-in classes throw TypeError when called as ordinary functions, but are still callable per the definition of IsCallable, as can be determined by seeing if Array.prototype.toString will attempt to use them as the implementation of 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 {}}));

Share Improve this question edited May 1, 2018 at 15:58 Bergi 667k161 gold badges1k silver badges1.5k bronze badges asked Apr 30, 2018 at 23:32 cpcallencpcallen 2,0651 gold badge17 silver badges31 bronze badges 2
  • 1 possible cases: Image and Option. There's nothing in the spec that would prevent such a thing from existing, but it would be very weird indeed. – Bergi Commented May 1, 2018 at 15:58
  • 1 possible duplicate of Is a constructor always a function object? – Bergi Commented May 7, 2018 at 13:23
Add a ment  | 

2 Answers 2

Reset to default 6

Restatement: Is it possible for an object X to return true for IsConstructor(X) but false for IsCallable(X)? I.e., is it possible for an object X to have a [[Construct]] internal method but not have a [[Call]] internal method?

The ECMAScript spec isn't as clear-cut on this point as it could be.

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

A function object is an object that supports the [[Call]] internal method. A constructor (also referred to as a constructor function) is a function object that supports the [[Construct]] internal method.

From this we can conclude that if such an object X does exist, it is clearly not a 'function object' and thus also not a 'constructor'. I.e. IsConstuctor(X) would return true for an object that isn't deemed a 'constructor', which would be odd.

(2) Note that in the clause that defines IsConstructor, the preamble says that it determines whether its argument "is a function object with a [[Construct]] internal method", but the algorithm doesn't have an explicit check that the argument is a function object. This suggests that (the spec-writer thought that) having a [[Construct]] internal method is sufficient to guarantee that the argument is a function object, i.e. that it has a [[Call]] internal method.

(3) The only point to having a [[Construct]] internal method is to invoke it in the Construct abstract operation. Similar to point (2), the preamble says that the operation "is used to call the [[Construct]] internal method of a function object", but the algorithm doesn't explicitly check that F is a function object.

So I believe the answer is that, while the spec doesn't explicitly say that such objects can't exist, it fairly strongly implies/assumes that they don't.


UPDATE (2018-05-22):

6.1.7.2 "Object Internal Methods and Internal Slots" has now been modified to say (emphasis mine):

A function object is an object that supports the [[Call]] internal method. A constructor is an object that supports the [[Construct]] internal method. Every object that supports [[Construct]] must support [[Call]]; that is, every constructor must be a function object. Therefore, a constructor may also be referred to as a constructor function or constructor function object.

No, it’s not possible to create something that’s constructible but not callable. Everything that defines a [[Construct]] in the spec is a function except for proxies, which only have [[Construct]] when their target also does (9.15.4).

A Proxy exotic object only has a [[Construct]] internal method if the initial value of its [[ProxyTarget]] internal slot is an object that has a [[Construct]] internal method.

发布评论

评论列表(0)

  1. 暂无评论