ES6+ Array.isArray()
1. 前言
在程序中判斷數(shù)組是很常見的應(yīng)用,但在 ES5 中沒有能嚴(yán)格判斷 JS 對象是否為數(shù)組,都會存在一定的問題,比較受廣大認(rèn)可的是借助 toString 來進行判斷,很顯然這樣不是很簡潔。ES6 提供了 Array.isArray()
方法更加簡潔地判斷 JS 對象是否為數(shù)組。
2. 方法詳情
判斷 JS 對象,如果值是 Array
,則為 true; 否則為 false。
語法使用:
Array.isArray(obj)
參數(shù)解釋:
參數(shù) | 描述 |
---|---|
obj | 需要檢測的 JS 對象 |
3. ES5 中判斷數(shù)組的方法
通常使用 typeof
來判斷變量的數(shù)據(jù)類型,但是對數(shù)組得到不一樣的結(jié)果
// 基本類型
typeof 123; //number
typeof "123"; //string
typeof true; //boolean
// 引用類型
typeof [1,2,3]; //object
上面的代碼中,對于基本類型的判斷沒有問題,但是判斷數(shù)組時,返回了 object 顯然不能使用 typeof
來作為判斷數(shù)組的方法。
3.1 通過 instanceof 判斷
instanceof
運算符用于檢測構(gòu)造函數(shù)的 prototype
屬性是否出現(xiàn)在某個實例對象的原型鏈。
instanceof
可以用來判斷數(shù)組是否存在,判斷方式如下:
var arr = ['a', 'b', 'c'];
console.log(arr instanceof Array); // true
console.log(arr.constructor === Array;); // true
在解釋上面的代碼時,先看下數(shù)組的原型鏈指向示意圖:
數(shù)組實例的原型鏈指向的是 Array.prototype
屬性,instanceof
運算符就是用來檢測 Array.prototype
屬性是否存在于數(shù)組的原型鏈上,上面代碼中的 arr 變量就是一個數(shù)組,所有擁有 Array.prototype
屬性,返回值 true
,這樣就很好的判斷數(shù)組類型了。
但是,需要注意的是,prototype
屬性是可以修改的,所以并不是最初判斷為 true
就一定永遠(yuǎn)為真。
在我們的網(wǎng)站中,腳本可以擁有多個全局環(huán)境,例如 html 中擁有多個 iframe 對象,instanceof
的驗證結(jié)果可能不會符合預(yù)期,例如:
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var iframeArray = window.frames[0].Array;
var arr = new iframeArray('a', 'b', 'c');
console.log(arr instanceof Array); // false
console.log(arr) // ["a", "b", "c"]
比如打開一個網(wǎng)站的控制臺,輸入上面的代碼,先在 body 上創(chuàng)建并添加一個 iframe 對象,并把它插入到當(dāng)前的網(wǎng)頁中。這時我們可以獲取 iframe 中數(shù)組構(gòu)造函數(shù)。通過這個構(gòu)造函數(shù)去實例化一個數(shù)組,這時再用 instanceof
去判斷就會返回 false,但是案例中的 arr 確實是一個數(shù)組,這就是 instanceof
判斷數(shù)組所帶來的問題。
3.2 通過 constructor 判斷
我們知道,Array 是 JavaScript 內(nèi)置的構(gòu)造函數(shù),構(gòu)造函數(shù)屬性(prototype)的 constructor
指向構(gòu)造函數(shù)(見下圖),那么通過 constructor
屬性也可以判斷是否為一個數(shù)組。
var arr = new Array('a', 'b', 'c');
arr.constructor === Array; //true
下面我們通過構(gòu)造函數(shù)的示意圖來進行分析:
由上面的示意圖可以知道,我們 new 出來的實例對象上的原型對象有 constructor
屬性指向構(gòu)造函數(shù) Array,由此我們可以判斷一個數(shù)組類型。
但是 constructor
是可以被重寫,所以不能確保一定是數(shù)組,如下示例:
var str = 'abc';
str.constructor = Array;
str.constructor === Array // true
上面的代碼中,str 顯然不是數(shù)組,但是可以把 constructor
指向 Array 構(gòu)造函數(shù),這樣再去進行判斷就是有問題的了。
constructor
和 instanceof
也存在同樣問題,不同執(zhí)行環(huán)境下,constructor
的判斷也有可能不正確,可以參考 instanceof
的例子。
4. Array.isArray () 的使用
下面我們通過示例來看下 Array.isArray()
是怎樣判斷數(shù)組的。
// 下面的函數(shù)調(diào)用都返回 true
Array.isArray([]);
Array.isArray([10]);
Array.isArray(new Array());
Array.isArray(new Array('a', 'b', 'c'))
// 鮮為人知的事實:其實 Array.prototype 也是一個數(shù)組。
Array.isArray(Array.prototype);
// 下面的函數(shù)調(diào)用都返回 false
Array.isArray();
Array.isArray({});
Array.isArray(null);
Array.isArray(undefined);
Array.isArray(17);
Array.isArray('Array');
Array.isArray(true);
Array.isArray(false);
Array.isArray(new Uint8Array(32))
Array.isArray({ __proto__: Array.prototype });
上面的代碼中對 JavaScript 中的數(shù)據(jù)類型做驗證,可以很好地區(qū)分?jǐn)?shù)組類型。
5. 自定義 isArray
在 ES5 中比較通用的方法是使用 Object.prototype.toString
去判斷一個值的類型,也是各大主流庫的標(biāo)準(zhǔn)。在不支持 ES6 語法的環(huán)境下可以使用下面的方法給 Array
上添加 isArray
方法
if (!Array.isArray){
Array.isArray = function(arg){
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
6. 小結(jié)
本節(jié)介紹了判斷一個值是數(shù)組類型的方法 Array.isArray()
此方法可以很準(zhǔn)確地判斷數(shù)組,學(xué)習(xí)了在 ES5 中判斷數(shù)組類型的幾個方法的缺陷。在不支持 ES6 的情況下也可以通過 Object.prototype.toString
自定義 Array.isArray()
方法。