判斷某個(gè)對(duì)象是否為Array?

題目:如何判斷一個(gè)js對(duì)象是否是Array,arr為要判斷的對(duì)象,其中最準(zhǔn)確的方法是?
A. typeof(arr)
B. arr instanceof Array
C. arr.toString==='[object Array]';
D. Object.prototype.toString.call(arr) === '[object Array]';

在開(kāi)發(fā)中,我們經(jīng)常需要判斷某個(gè)對(duì)象是否為數(shù)組類型,在Js中檢測(cè)對(duì)象類型的常見(jiàn)方法都有哪些呢?

typeof操作符

typeof操作符可能返回下列某個(gè)字符串:

  • "undefined" —— 值未定義
  • "boolean"
  • "string"(小寫)
  • "number"
  • "object" —— 這個(gè)值是對(duì)象或者null
  • "function"
typeof []; // "object"
  • 對(duì)于Function, String, Number ,Undefined 等幾種類型的對(duì)象來(lái)說(shuō),他完全可以勝任,但是為Array時(shí),就會(huì)得到object。
  • 這是因?yàn)椋簲?shù)組屬于js對(duì)象,用此操作符檢測(cè)只能返回"object"

instanceof操作符

instanceof 運(yùn)算符用來(lái)測(cè)試一個(gè)對(duì)象在其原型鏈中是否存在一個(gè)構(gòu)造函數(shù)的 prototype 屬性。

語(yǔ)法

object instanceof constructor
//object需檢測(cè)對(duì)象
//constructor某個(gè)構(gòu)造函數(shù)

描述
instanceof 運(yùn)算符用來(lái)檢測(cè) constructor.prototype是否存在于參數(shù) object 的原型鏈上。

深入理解instanceof

instanceof和多全局對(duì)象(多個(gè)frame或多個(gè)window之間的交互)
在瀏覽器中,我們的腳本可能需要在多個(gè)窗口之間進(jìn)行交互。多個(gè)窗口意味著多個(gè)全局環(huán)境,不同的全局環(huán)境擁有不同的全局對(duì)象,從而擁有不同的內(nèi)置類型構(gòu)造函數(shù)。這可能會(huì)引發(fā)一些問(wèn)題。
比如,表達(dá)式[] instanceof window.frames[0].Array會(huì)返回false,因?yàn)?Array.prototype !== window.frames[0].Array.prototype,因此你必須使用 Array.isArray(myObj) 或者 Object.prototype.toString.call(myObj) === "[object Array]"來(lái)判斷myObj是否是數(shù)組。

  • 栗子
//1.正常情況下
[] instanceof Array   //true

//2.多個(gè)frame交互時(shí)——就會(huì)產(chǎn)生大問(wèn)題了。
var iframe = document.createElement('iframe');    
document.body.appendChild(iframe);    
xArray = window.frames[window.frames.length-1].Array;       
var arr = new xArray("1","2","3","4","5");//這個(gè)寫法IE大哥下是不支持的,F(xiàn)F下才有       
alert(arr instanceof Array); // false 
alert(arr.constructor === Array); // false  

//3.萬(wàn)全判斷方法
Array.isArray(arr);  // true
Object.prototype.toString.call(arr) === "[object Array]" ;   //true
  • 當(dāng)檢測(cè)Array實(shí)例時(shí), Array.isArray 優(yōu)于 instanceof,因?yàn)锳rray.isArray能檢測(cè)iframes.

Object.prototype.toString.call(obj)

ECMA-262 寫道
Object.prototype.toString( ) When the toString method is called, the following steps are taken:

  1. Get the [[Class]] property of this object.
  2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.
  3. Return Result (2)

上面的規(guī)范定義了Object.prototype.toString的行為:
首先,取得對(duì)象的一個(gè)內(nèi)部屬性[[Class]],然后依據(jù)這個(gè)屬性,返回一個(gè)類似于"[object Array]"的字符串作為結(jié)果(看過(guò)ECMA標(biāo)準(zhǔn)的應(yīng)該都知道,[[]]用來(lái)表示語(yǔ)言內(nèi)部用到的、外部不可直接訪問(wèn)的屬性,稱為“內(nèi)部屬性”)。利用這個(gè)方法,再配合call,我們可以取得任何對(duì)象的內(nèi)部屬性[[Class]],然后把類型檢測(cè)轉(zhuǎn)化為字符串比較,以達(dá)到我們的目的。還是先來(lái)看看在ECMA標(biāo)準(zhǔn)中Array的描述吧。

ECMA-262 寫道
new Array([ item0[, item1 [,…]]])
The [[Class]] property of the newly constructed object is set to “Array”

  • 于是:
if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
  • 分析:

call改變toString的this引用為待檢測(cè)的對(duì)象,返回此對(duì)象的字符串表示,然后對(duì)比此字符串是否是'[object Array]',以判斷其是否是Array的實(shí)例。也許你要問(wèn)了,為什么不直接o.toString()?嗯,雖然Array繼承自O(shè)bject,也會(huì)有toString方法,但是這個(gè)方法有可能會(huì)被改寫而達(dá)不到我們的要求,而Object.prototype則是老虎的屁股,很少有人敢去碰它的,所以能一定程度保證其“純潔性”:)

與前面幾個(gè)方案不同,這個(gè)方法很好的解決了跨frame對(duì)象構(gòu)建的問(wèn)題,經(jīng)過(guò)測(cè)試,各大瀏覽器兼容性也很好,可以放心使用。一個(gè)好消息是,很多框架,比如jQuery、Base2等等,都計(jì)劃借鑒此方法以實(shí)現(xiàn)某些特殊的,比如數(shù)組、正則表達(dá)式等對(duì)象的類型判定,不用我們自己寫了。

另外ECMA已經(jīng)換成這樣的寫法:

isArray : function(v){
   return toString.apply(v) === '[object Array]';
 }

參考博文:
js如何判斷一個(gè)對(duì)象是不是Array?
Array.isArray()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容