Alternative isFunction Implementations with verifications and several test types
JavaScript performance comparison
Info
Extended tests with verification that the isFunction implementations return the expected value. Based on the original by Kit Goncharov and two unmarked edits. Saw the link on StackOverflow: How can I check if a javascript variable is function type?.
This test case compares four alternative isFunction implementations:
isFunctionAchecks the internal[[Class]]name of an object to determine if it is a function. Unfortunately, while this check is the most reliable, it's also less efficient due to the extra call toObject#toString.isFunctionBwas proposed as an alternative to thetypeofandinstanceofoperators by Garrett Smith. This implementation uses duck-typing, so it may produce incorrect results.isFunctionCis currently used in Underscore.js. This implementation uses only basic duck-typing; thus, it is the most likely to produce incorrect results.isFunctionDuses onlytypeofto check for a "function".
There are also two duplicate versions of A and D, Ab and Db, which uses strict equality.
Please open your console and check for error messages. It seems that isFunctionA (and Ab) fails "emptyStr" and "undefined".
Preparation code
<script>
var
// used in isFunction implementations
getClass = {}.toString,
hasProperty = {}.hasOwnProperty,
// Test data
noop = function(){},
objectToString = {}.toString,
objectHasOwnProperty = {}.hasOwnProperty,
expression = /Kit/g,
browserAlert = alert,
objectConstructor = Object,
dateConstructor = Date,
stringConstructor = String,
int = 12345,
emptyStr = "",
longStr = "abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789 abcdefghijklmnopqrstuvwxyz0123456789";
// Checks the internal [[Class]] name of the object.
function isFunctionA(object) {
return object && getClass.call(object) == '[object Function]';
}
// Partial duck-typing implementation by Garrett Smith.
function isFunctionB(object) {
if (typeof object != 'function') return false;
var parent = object.constructor && object.constructor.prototype;
return parent && hasProperty.call(parent, 'call');
}
// Pure duck-typing implementation taken from Underscore.js.
function isFunctionC(object) {
return !!(object && object.constructor && object.call && object.apply);
}
// Simple typeof comparison
function isFunctionD(object) {
return typeof(object) == 'function';
}
// Checks the internal [[Class]] name of the object.
// (with strict equality)
function isFunctionAb(object) {
return object && getClass.call(object) === '[object Function]';
}
// Simple typeof comparison
// (with strict equality)
function isFunctionDb(object) {
return typeof(object) === 'function';
}
function benchmarkIsFunction(fnc)
{
fnc(noop);
fnc(objectToString);
fnc(objectHasOwnProperty);
fnc(expression);
fnc(browserAlert);
fnc(objectConstructor);
fnc(dateConstructor);
fnc(stringConstructor);
fnc(int);
fnc(emptyStr);
fnc(longStr);
fnc(undefined);
}
function verify(verified, fnc, name, data)
{
if(!verified && typeof console !== "undefined" && typeof console.error !== "undefined")
{
console.error(name + " failed the functionality test for data " + data);
}
}
function verifyIsFunction(fnc, name)
{
verify(fnc(noop) === true, fnc, name, "noop");
verify(fnc(objectToString) === true, fnc, name, "objectToString");
verify(fnc(objectHasOwnProperty) === true, fnc, name, "objectHasOwnProperty");
verify(fnc(expression) === false, fnc, name, "expression");
verify(fnc(browserAlert) === true, fnc, name, "browserAlert");
verify(fnc(objectConstructor) === true, fnc, name, "objectConstructor");
verify(fnc(dateConstructor) === true, fnc, name, "dateConstructor");
verify(fnc(stringConstructor) === true, fnc, name, "stringConstructor");
verify(fnc(int) === false, fnc, name, "int");
verify(fnc(emptyStr) === false, fnc, name, "emptyStr");
verify(fnc(longStr) === false, fnc, name, "longStr");
verify(fnc(undefined) === false, fnc, name, "undefined");
}
verifyIsFunction(isFunctionA, "A");
verifyIsFunction(isFunctionB, "B");
verifyIsFunction(isFunctionC, "C");
verifyIsFunction(isFunctionD, "D");
verifyIsFunction(isFunctionAb, "Ab");
verifyIsFunction(isFunctionDb, "Db");
</script>
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
isFunctionA |
|
pending… |
isFunctionB |
|
pending… |
isFunctionC |
|
pending… |
isFunctionD |
|
pending… |
isFunctionAb (strict equality) |
|
pending… |
isFunctionDb (strict equality) |
|
pending… |
Compare results of other browsers
Revisions
You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:
- Revision 1: published by Kit Goncharov
- Revision 2: published
- Revision 3: published
- Revision 4: published by Joel Purra
0 comments