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);