andy-h
12/20/2013 - 2:14 PM

Improved JavaScript type testing

Improved JavaScript type testing

//classof(o)
//is.undefined(o)
//is.defined(o)
//is.null(o)
//is.Boolean(o)
//is.Number(o)
//is.String(o)
//is.RegExp(o)
//is.Date(o)
//is.Array(o)
//is.Function(o)
//is.Object(o)
//is.primitive(o)
//is.realNumber(o)
//is.infiniteNumber(o)
//is.NaN(o)

(function (){
	
	"use strict";
	
	var objStr = function (o){ return Object.prototype.toString.call(o); },
		inf = 1/0,
		is = {};
	
	//a `typeof` alternative
	function classof(o){
		var t = typeof o;
		if(o === void 0) return "undefined";
		if(t === "object") return o === null ? "null" : objStr(o).slice(8,-1);
		return t[0].toUpperCase()+t.slice(1);	//function, number, string, or boolean
	}
	
	function isUndefined(o){ return o === void 0; }
	function isDefined(o){ return o !== void 0; }
	function isNull(o){ return o === null; }
	
	function isBoolean(o){ var t; return (t = typeof o) === "boolean" || t === "object" && objStr(o) === "[object Boolean]"; }
	function isNumber(o){ var t; return (t = typeof o) === "number" || t === "object" && objStr(o) === "[object Number]"; }
	function isString(o){ var t; return (t = typeof o) === "string" || t === "object" && objStr(o) === "[object String]"; }
	function isRegExp(o){ return typeof o === "object" && objStr(o) === "[object RegExp]"; }
	function isDate(o){ return typeof o === "object" && objStr(o) === "[object Date]"; }
	function isArray(o){ return typeof o === "object" && objStr(o) === "[object Array]"; }
	function isFunction(o){ return typeof o === "function"; }
	
	//test if it's an infinite number
	//note: JavaScript treats a non-zero real number divided by zero as Infinity (but it's actually an undefined form)
	function isInfiniteNumber(o){ return Math.abs(o) === inf; }
	
	//test if it's a number, string, or date representing a real number
	function isRealNumber(o){ return (isNumber(o) || (isString(o) && o) || isDate(o)) && !isNaN(o) && !isInfiniteNumber(o); }
	
	function isPrimitive(o){ var t; return o===t || o===null || (t = typeof o)==="number" || t==="string" || t==="boolean"; }
	function isObject(o){ return !isPrimitive(o); };
	
	
	if(isUndefined(this.classof)){
		this.classof = classof;
	}
	
	if(isUndefined(this.is)){
		is.undefined = isUndefined;
		is.defined = isDefined;
		is.null = isNull;
		
		is.Boolean = isBoolean;
		is.Number = isNumber;
		is.String = isString;
		is.RegExp = isRegExp;
		is.Date = isDate;
		is.Array = isArray;
		is.Function = isFunction;
		
		is.Object = isObject;
		is.primitive = isPrimitive;
		
		is.realNumber = isRealNumber;
		is.infiniteNumber =  isInfiniteNumber;
		is.NaN = Number.isNaN;  //tests if the argument is the actual value `NaN`
								//`isNaN(x)` coerces the argument into a number first, the same as doing this: `Number.isNaN(Number(x))`
								//note: JavaScript doesn't treat all undefined forms as NaN (e.g., 1/0 or 0^0))
		
		this.is = is;
	}
	
}).call(this);