題目:如何判斷一個(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和多全局對(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:
- Get the [[Class]] property of this object.
- Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.
- 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]';
}