Type Detection Revisited
Mikol Graves, recently commented on my Type Detection article showing a novel way to do type detection. Here is his code snippet:
function isTYPE(o) { return (o != null && typeof o == ‘object’ && o.constructor.toString() == TYPE.toString()); }
For each Object type that you care about, for example: Date, Array, Class, to name a few. You simply replace “TYPE” with the appropriate Object name. These examples would produce functions like:
function isArray(o) { return (o != null && typeof o == ‘object’ && o.constructor.toString() == Array.toString()); } function isDate(o) { return (o != null && typeof o == ‘object’ && o.constructor.toString() == Date.toString()); } function isClass(o) { return (o != null && typeof o == ‘object’ && o.constructor.toString() == Class.toString()); }
This is nice, because it gives you a way of detecting all kinds of Meta Object types that you might care about. However, you end up using the same code over and over again. Therefore, I took some time and looked around the different toolkits for various other ways that type detection was being done. I found a snippet of code that I really liked in mootools.v1.11. Here is the code:
/* Section: Core Functions */ /* Function: $defined Returns true if the passed in value/object is defined, that means is not null or undefined. Arguments: obj - object to inspect */ function $defined(obj){ return (obj != undefined); }; /* Function: $type Returns the type of object that matches the element passed in. Arguments: obj - the object to inspect. Example: >var myString = ‘hello’; >$type(myString); //returns “string” Returns: ‘element’ - if obj is a DOM element node ‘textnode’ - if obj is a DOM text node ‘whitespace’ - if obj is a DOM whitespace node ‘arguments’ - if obj is an arguments object ‘object’ - if obj is an object ’string’ - if obj is a string ‘number’ - if obj is a number ‘boolean’ - if obj is a boolean ‘function’ - if obj is a function ‘regexp’ - if obj is a regular expression ‘class’ - if obj is a Class. (created with new Class, or the extend of another class). ‘collection’ - if obj is a native htmlelements collection, such as childNodes, getElementsByTagName .. etc. false - (boolean) if the object is not defined or none of the above. */ function $type(obj){ if (!$defined(obj)) return false; if (obj.htmlElement) return ‘element’; var type = typeof obj; if (type == ‘object’ && obj.nodeName){ switch(obj.nodeType){ case 1: return ‘element’; case 3: return (/S/).test(obj.nodeValue) ? ‘textnode’ : ‘whitespace’; } } if (type == ‘object’ || type == ‘function’){ switch(obj.constructor){ case Array: return ‘array’; case RegExp: return ‘regexp’; case Class: return ‘class’; } if (typeof obj.length == ‘number’){ if (obj.item) return ‘collection’; if (obj.callee) return ‘arguments’; } } return type; };
This was a good foundation for an improvement upon my type detection Functions. The $type Function can detect nearly all of my “isType” Functions straight away and has the power to detect some other important types, such as: arguments, textnode, element, collection, and more. So far, I have only added Date in addition to the types already defined and created an additional Function “isType” which can be used to test the object against a desired type.
We lose, “isAlien” Function and whether the number is finite. However, I never use these anymore, so I do not really need them. So far I believe the benefit of using these Functions will out-weight the loss. Although, I have also found these issues: testing for ‘whitespace’ does not work with IE because IE ignores whitespaces when parsing the DOM; in Opera testing for ‘arguments’ will return ‘array’, because Arguments constructor is Array (go figure). Otherwise, it has worked flawlessly and these issues can be worked around. I put together a test page, to verify the results of the isType Function and checked variations on the most common browsers.
You can download my Type Detection JavaScript file.
