在進行編程開發時,我們往往需要對一些不可確定的數據進行類型判定 。但是僅僅藉助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+'');
}