Are there any significant reasons for using
typeof variable === \'function\'
versus
!!variable.call
for d
jQuery's isFunction avoids the RegExp
problem you mention by toString
-ing the object and checking the result against a map of known types. From the latest source, here's the map:
// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
And here's how it's used:
type: function( obj ) {
return obj == null ?
String( obj ) :
class2type[ toString.call(obj) ] || "object";
},
// See test/unit/core.js for details concerning isFunction.
// Since version 1.3, DOM methods and functions like alert
// aren't supported. They return false on IE (#2968).
isFunction: function( obj ) {
return jQuery.type(obj) === "function";
},
You can learn a lot reading the jQuery source.
The safest way is to check the internal [[Class]] property by setting the object as the thisArg argument of the .call()
method when calling Object.prototype.toString
.
Object.prototype.toString.call( myVariable ) === '[object Function]';
Of course you could easily make a function out of it:
function checkClass( obj ) {
return Object.prototype.toString.call( obj ).slice( 8, -1).toLowerCase();
}
checkClass( myVariable ) === 'function';
This is very simple, and there could be some improvements, but you get the idea.
typeof variable === 'function'
is better than !!variable.call
because if variable is undefined or null, !!variable.call
will throw an error.
According to the ECMAScript specification, the following should apply for regular expression literals:
A regular expression literal is an input element that is converted to a RegExp object (section 15.10) when it is scanned. The object is created before evaluation of the containing program or function begins.
So typeof /regex/
should yield "object"
:
typeof /regex/ === "object"
And the constructor of the object created by the regular expression literal should be RegExp:
/regex/.constructor === RegExp
Similar to that, a function definition should yield a Function object:
(function(){}).constructor === Function
But although this returns a Function object, the typeof operator should not yield "object"
but "function"
instead:
typeof function(){} === "function"
This is due to the distinction whether the object implements the internal [[Call]] property that is special for Function objects.
Note that all this is how Javascript implementations should behave. So all equations are asserted to be true.
A regular expression is a function
/bar/("bar") === ["bar"]
So typeof /bar/ === "function"
Although only chrome recognises that a regexp literal can be used as a function. Whether this should be so or not is up for grabs. You can treat it just like a function!
Check the assumptions in the post (see Gumbo's comment).
typeof /regex/ === 'function'
This returns false
in Firefox 3.6.13.
Just for amusement, Firefox 3.6.13:
typeof /regex/ // "object"
/regex/ instanceof RegExp // true
/regex/.constructor.name // RegExp
(function () {}).constructor.name // Function
IE8:
typeof /regex/ // "object"
/regex/ instanceof RegExp // true
/regex/.constructor.name // undefined
(function () {}).constructor.name // undefined
Chrome 9:
typeof /regex/ // "function"
/regex/ instanceof RegExp // true
/regex/.constructor.name // "RegExp"
(function () {}).constructor.name // "Function"