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:
/*
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.