The getVarType method (below) works for almost all variables. Check out this fiddle. It first uses the very fast typeof for cases where the results are reliable. Then it uses a more expensive toString method for other cases. Finally, if it is dealing with a named object (as returned by Firefox for objects like document.location) it checks for Array-like objects and reports them as arrays.
In comparison, typeof is embarrassingly poor. typeof([]) returns 'object', typeof(new Number()) returns object. It also returns 'object' for many other variables that aren't (for practical purposes) objects. See the fiddle results for a comparison.
// Begin public utility /getVarType/
// Returns 'Function', 'Object', 'Array',
// 'String', 'Number', 'Null', 'Boolean', or 'Undefined'
//
getVarType = (function () {
var typeof_map = {
'undefined' : 'Undefined',
'boolean' : 'Boolean',
'number' : 'Number',
'string' : 'String',
'function' : 'Function',
'Undefined' : 'Undefined',
'Null' : 'Null',
'Boolean' : 'Boolean',
'Number' : 'Number',
'String' : 'String',
'Function' : 'Function',
'Array' : 'Array',
'StyleSheetList' : 'Array'
};
return function( data ) {
var type, type_str;
if ( data === null ) { return 'Null'; }
if ( data === undefined ) { return 'Undefined'; }
type = typeof( data );
type_str = typeof_map[ type ];
if ( type_str ) { return type_str; }
type = {}.toString.call( data ).slice( 8, -1 );
return typeof_map[ type ]
|| ( data instanceof Array ? 'Array' :
( data.propertyIsEnumerable(0) && data.length !== undefined
? 'Array' : 'Object' )
);
};
}());
// End public utility /getVarType/
The only possible failure mode happens if you are testing a named array that is empty (e.g. an empty enumerable DOM object besides the StyleSheetList). But on could add those to the type_of_map as needed.
I hope that helps!