在进行编程开发时,我们往往需要对一些不可确定的数据进行类型判定 。但是仅仅借助JavaScript自带的typeof 和instanceof 这两个方法似乎并不能满足我们的需求。
首先 使用typeof 和instanceof 所能分辨出的类型是比较模糊的,以typeof 举例的话他能识别出string 、number 、boolean 、 function 、undefined 、object 这6种类型,但是无法识别null , RegExp 、Argument、window 等类型 。
另外由于浏览器兼容问题,在编写自定义类型判定的hack时,我们也可能会遇到各种坑。在这里与大家分享个人在进行部分类型判定时常使用的方法。这些方法处理了兼容问题,已经在一些经典的库文件中被应用,所以你也可以放心大胆的去使用它们:
function isArray(o) { // 检测数组
// 在满足基本鸭子类型的情况下
if( o && typeof o=='object'&& typeof o.length === 'number' && isFinite(o.length))
{
// 如果添加元素后数组长度会自动改变
var _origLength = o.length;
o[o.length] = '_test_';
var _newLength = o.length;
o.length = _origLength; // 为了不改变原数组
return _newLength == _origLength+1;
}
return false;
}
functionisNaN(obj) { // 检测NaN
return obj!==obj;
}
function isNull(obj) { // 检测Null
return obj===null;
}
functionisUndefined(obj) { // 检测undefined
return obj=== void 0;
}
functionisWindow(obj) { // 检测window对象
// ie 678 下
// window == document //true
// document == window //false
if((obj==document)&&!(document==obj)||(obj!=null&&obj==obj.window))
{
return true;
}
return false;
}
functionisArrayLike(obj) { // 检测类数组
if(obj && typeof obj ==="object")
{
var n = obj.length,
str =Object.prototype.toString.call(obj);
if(/Array|NodeList|Arguments|CSSRuleList/.test(str))
{
return true;
}else if(str==='[object Object]'&& (+n ===n && !(n%1) && n>=0))
{
return true;
}
}
return false;
}
function isPlainObject(obj) { // 检测是否为纯净的JavaScript对象(既不是dom,bom对象,也不是自定义 ’类’ 的实例对象)
// 排除基础类型不是Object的类型、dom节点 、window 对象
if(typeof obj !=='object' || obj.nodeType|| isWindow(obj)){
return false;
} // 检测原型对象是否有isPrototypeOf
try { // 旧版本的一些原生对象没有暴露constructor、prototype 会报错
if(obj.constructor &&!({}).hasOwnProperty.call(obj.constructor.prototype,"isPrototypeOf"))
{
return false;
}
}catch (e)
{
return false;
}
return true;
}
functionisFunction(fn) { // 检测是否为函数
return !!fn && typeof fn !="string" && !fn.nodeName &&
fn.constructor != Array &&/^[\s[]?function/.test(fn+'');
}