Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any JS objects for which IsCallable is false but IsConstructor is true?

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 {}}));
like image 369
cpcallen Avatar asked Mar 07 '23 07:03

cpcallen


2 Answers

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.

like image 173
Michael Dyck Avatar answered Mar 08 '23 21:03

Michael Dyck


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.

like image 31
Ry- Avatar answered Mar 08 '23 21:03

Ry-