Using IsCallable Operation?

# Garrett Smith (16 years ago)

There seems to be a lot of controversy on how to properly check if something should be callable. There isn't any way to determine that in ES3.

The internal IsCallable determines if an object has a [[Call]] property.

Will that be available as a language feature, not internal?

For example:- Object.isCallable( document.images );

  • would provide a check to internal IsCallable and return the result.

Garrett

# Allen Wirfs-Brock (16 years ago)

Not in ES5. Generally checking that typeof x === 'function' is a close approximation. ES5 (11.4.3) requires that both native (ie, pure actual ECMAScript objects) and host objects that implement [[Call]] produce "function" when typeof is applied to them. This is a change from ES3 that did not impose this requirement upon host object objects.

Of course it may take a while for browser implementations to respond to this change.

# Mark S. Miller (16 years ago)

On Fri, Jun 5, 2009 at 1:39 PM, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com> wrote:

Not in ES5.  Generally checking that typeof x === 'function' is a close approximation. ES5 (11.4.3) requires that  both native (ie, pure actual ECMAScript objects) and host objects that implement [[Call]] produce "function" when typeof is applied to them.  This is a change from ES3 that did not impose this requirement upon host object objects.

Why is this an approximation? In ES5, how can typeof x === 'function' differ from testing whether something is callable?

# Allen Wirfs-Brock (16 years ago)

Well, it depends upon implementations actually adhering to the typeof specification (which may take some time to come about). In ES5 IsCallable is a specification device that essentially means you really truly can call it (which is what it means to have a [[Call]] specification method).

# Garrett Smith (16 years ago)

On Fri, Jun 5, 2009 at 2:18 PM, Mark S. Miller<erights at google.com> wrote:

On Fri, Jun 5, 2009 at 1:39 PM, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com> wrote:

Not in ES5.  Generally checking that typeof x === 'function' is a close approximation. ES5 (11.4.3) requires that  both native (ie, pure actual ECMAScript objects) and host objects that implement [[Call]] produce "function" when typeof is applied to them.  This is a change from ES3 that did not impose this requirement upon host object objects.

Why is this an approximation? In ES5, how can    typeof x === 'function' differ from testing whether something is callable?

ES5 typeof table: +--------------------------+------------+ | Object (native or host | "function" | | and implements [[Call]]) | | +--------------------------+------------+

That is an idealistic change. IMO ES3 should have had that.

Microsoft could have taken a cue from the ES3 spec behavior for typeof with "object that implements call" and had the typeof operator return "function" instead of one of "function", "object", or "unknown".

One could theoretically perform a capability test on the typeof operator, but that would not be practical because implementations today have varied results with the typeof operator on host objects.

The classic document.images problem originates from IE. The document.images collection is callable in Safari, Opera, Chrome, and IE and most likely several other browsers.

typeof document.images

  • "function" in Safari, "object" in IE Chrome and Opera 9+. Also "object" in Gecko (where it is not callable).

Testing the document.images collection to see if is callable can't work with a typeof operator that is inconsistent across versions of the language.

A hand-rolled isCallable method that has a (poor) fallback (the current "best practices") could expect the new behavior specified for typeof operator if and only if it was known to the program be the newer typeof.

function isCallable(obj, prop) { var type = typeof obj[prop]; if(isNewTypeof) { return type === "function"; } else { // fallback "best practice". } }

That code requires an "isNewTypeof" variable. A strategy for determining the correct value of isNewTypeof would be an impossibility.

I think it would be worth considering a native isCallable method.

Garrett

# Mark S. Miller (16 years ago)

On Fri, Jun 5, 2009 at 7:22 PM, Garrett Smith <dhtmlkitchen at gmail.com>wrote:

function isCallable(obj, prop) { var type = typeof obj[prop]; if(isNewTypeof) { return type === "function"; } else { // fallback "best practice". } }

function isCallable(obj, prop) { var type = typeof obj[prop]; if (function(){"use strict";return this;}()) { // fallback "best practice". } else { return type === "function"; } }