Alternative isFunction Implementations with verifications and several test types

JavaScript performance comparison

Revision 4 of this test case created by Joel Purra

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:

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.

Testing in unknown unknown
Test Ops/sec
isFunctionA
benchmarkIsFunction(isFunctionA)
pending…
isFunctionB
benchmarkIsFunction(isFunctionB)
pending…
isFunctionC
benchmarkIsFunction(isFunctionC)
pending…
isFunctionD
benchmarkIsFunction(isFunctionD)
pending…
isFunctionAb (strict equality)
benchmarkIsFunction(isFunctionAb)
pending…
isFunctionDb (strict equality)
benchmarkIsFunction(isFunctionDb)
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:

0 comments

Add a comment