前面《變量的賦值和對象的賦值》中有用到typeof運算符去判斷運算數的類型,結果如下:
alert(typeof 1); // 返回字符串"number" alert(typeof "1"); // 返回字符串"string" alert(typeof true); // 返回字符串"boolean" alert(typeof {}); // 返回字符串"object" alert(typeof []); // 返回字符串"object " alert(typeof function(){}); // 返回字符串"function" alert(typeof null); // 返回字符串"object" alert(typeof undefined); // 返回字符串"undefined"
其中,typeof {}和typeof []的結果都是object,那么問題來了,我怎么通過typeof去判斷一個對象是不是數組類型呢?
對象是對象,數組也是對象,js中萬物皆對象,很顯然,通過簡單的typeof運算符是不能夠達到目的,我們得換個方法。
---------------------------------------------------------------------------------------------------------------------------
可以嘗試以下幾種方法:
1、從原型入手,Array.prototype.isPrototypeOf(obj);
利用isPrototypeOf()方法,判定Array是不是在obj的原型鏈中,如果是,則返回true,否則false。
2、也可以從構造函數入手,obj instanceof Array
先說說 typeof 和 instanceof 的區別?
兩者都可以用來判斷變量,typeof會返回基本類型,如文章開頭,我們很簡單可以用
typeof a != 'undefined' 判斷a變量存在。而instanceof只會返回一個布爾值,那么我們試試,結果如下:
上面的方法其實也可以用對象constructor屬性,因為在js中每個對象都有constructor屬性,這種也常用作判斷未知對象的類型。
例如:typeof arr == "object" && arr.constructor == Array; //先判斷是對象再進一步判斷。
那樣是不是這個方法就ok了?別開心那么早,坑總是會有的。
在一些跨框架的頁面中的數組,使用該方法可能不會那么順利,原因是在不同的框架中創建的數組不會相互共享其prototype屬性。
問題總是要解決的,有沒有更加精確的方法呢?==果真有啊!
3、根據對象的class屬性(類屬性),跨原型鏈調用toString()方法。
解釋一下,在js中一個對象一旦被創建,在內部會攜帶創建對象的類型名,一旦創建就不能被修改了。那么怎么獲取這個對象的類型名呢?
js中提供了,調用對象原型中的toString方法, Object.prototype.toString.call(obj);因為很多對象繼承的toString()方法被重寫了,為了能夠調用正確的toString()版本,也就是最原始的版本。可以使用Function.call()的方法,其中call可以這么理解,相當於obj去借用這個 Object.prototype.toString();
Object.prototype.toString.call(new Date()); //"[object Date]" Object.prototype.toString.call(Window); //"[object window]" Object.prototype.toString.call(/./); //"[object RegExp]"
那么有了這個方法,獲取對象名可以這樣獲取:
或者這么寫:
function _getClass(o){ if(o===null) return "Null"; if(o===undfined) return "undefined"; return Object.prototype.toString.call(o).slice(8,-1); }
4、Array.isArray()方法。
其實js已經提供了判斷是不是數組類型的方法,如下:
Array.isArray([1, 2, 3]); // true Array.isArray({foo: 123}); // false Array.isArray('foobar'); // false Array.isArray(undefined); // false
在MDN中就比較了isArray和instanceof的區別,當Array.isArray()不可用的使用,MDN做了如下的補丁,說明還是比較推薦使用前面講的第三種方法 Object.prototype.toString.call(obj)。
以上四種方法夠用了吧?
-----------------------------------------------------end---------------------------------------------------------------------------