Now Available in YourJS

John Resig definitely has some awesome code inside of jQuery. One of the things that I think is cool is how jQuery does type checking. After looking through the code, I developed my own flavor of functions using the same principle. Here is the code that I was able to come up with:

(function() {
  var types = "Object null undefined Array Boolean Date Error Function Number RegExp String".split(" ");
  // Defines the getTypeOf() function on the local and global level.
  // Local variable also declared to prevent errors that would occur
  // from externally redefining getTypeOf().
  var getTypeOf = this.getTypeOf = function(arg) {
    return arg == null
      ? arg + ""
      : types[Object.prototype.toString.call(arg)] || "Object";
  };
  // Defines isNull(), isUndefined(), isArray(), isBoolean(), isDate(),
  // isError(), isFunction(), isNumber(), isObject(), isRegExp(), and
  // isString() on the global level.
  for(var i = types.length - 1; i >= 0; i--) {
    types[i > 1 ? "[object " + types[i] + "]" : types[i]] = types[i];
    (function(type) {
      this["is" + type.charAt(0).toUpperCase() + type.substring(1)] = function(arg) {
        return getTypeOf(arg) == type;
      };
    })(types[i]);
  }
  i = this.isObject;
  this.isObject = function(arg, allowAnyType) {
    return allowAnyType ? arg != null : i(arg);
  };
})();

Basically, my getTypeOf() function is just like jQuery’s jQuery.type() function with one exception. All of the types that are returned, with the exception of undefined and null, are returned as in the same casing as their constructor. In other words, where jQuery.type(/re/) would return "regexp", getTypeOf(/re/) would return "RegExp".

The other function that are created are isNull(), isUndefined(), isArray(), isBoolean(), isDate(), isError(), isFunction(), isNumber(), isObject(), isRegExp(), and isString(). The isObject() function is can take one or two parameters. If one parameter is passed in or two are passed in and the second one evaluates to false, the boolean returned will indicate whether or not the specified argument was an object that is not an array, boolean, date, error, function, number, regular expression or string. If two parameters are passed and the second evaluates to true, the function will return true if the argument is not null or undefined, otherwise it will return false. All of the other functions take one parameter and return a boolean indicating whether or not the type is as specified by the function name.

The following is how I tested the functions:

// Test the specified object on all of the new functions.
function testOnAll(obj, strObj) {
  var arr = "Array Boolean Error Date Function Null Number Object RegExp String Undefined".split(" ");
  for(var i = arr.length - 1; i >= 0; i--) {
    if(arr[i] == "Object") {
      arr.splice(i + 1, 0, eval("is" + arr[i])(obj, true) + " <= isObject(" + strObj + ", true)");
    }
    arr[i] = eval("is" + arr[i])(obj) + " <= is" + arr[i] + "(" + strObj + ")";
  }
  arr.unshift('"' + getTypeOf(obj) + '" <= getTypeOf(' + strObj + ")");
  alert(arr.join("\n"));
}
// All of the tests which display the type of the object and
// the evaluation after using all of the new is functions.
testOnAll("Hello", '"Hello"');
testOnAll([1,2,"Three",[4,[[5]]]], '[1,2,"Three",[4,[[5]]]]');
testOnAll(false, 'false');
testOnAll(null, 'null');
testOnAll(undefined, 'undefined');
testOnAll(window, 'window');
testOnAll(alert, 'alert');
testOnAll(function(){}, 'function(){}');
testOnAll(/#/, '/#/');
testOnAll(new Date(), 'new Date()');
testOnAll(2342, '2342');
testOnAll(3981.3491, '3981.3491');
testOnAll(NaN, 'NaN');
testOnAll(-Infinity, '-Infinity');
testOnAll({}, '{}');
testOnAll(new Object(), 'new Object()');
testOnAll(new (function(){}), 'new (function(){})');
testOnAll(new Error("an error"), 'new Error("an error")');
testOnAll(new EvalError("an error"), 'new EvalError("an error")');
testOnAll(new SyntaxError("an error"), 'new SyntaxError("an error")');
testOnAll(new TypeError("an error"), 'new TypeError("an error")');
testOnAll(new RangeError("an error"), 'new RangeError("an error")');
testOnAll(new ReferenceError("an error"), 'new ReferenceError("an error")');
testOnAll(new URIError("an error"), 'new URIError("an error")');

I think it is important to note that using getTypeOf(NaN) will result in "Number" because NaN is a number object believe it or not. This is the same reason that isNumber(NaN) returns true. As far as I can tell, all of the other tests evaluate as expected.

Categories: BlogJavaScriptJScript

1 Comment

JavaScript – Better typeOf() Function | Chris West's Blog · July 3, 2012 at 12:09 PM

[…] while back, I wrote a function about Solid Type Checking. What is funny is that I often am writing just a bit of JavaScript in which I need a better way of […]

Leave a Reply

Your email address will not be published. Required fields are marked *