Using IsCallable Operation?

Garrett Smith dhtmlkitchen at gmail.com
Fri Jun 5 19:22:53 PDT 2009


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


More information about the es-discuss mailing list