javascript判斷一個對象是否爲數組

在JavaScript中,能夠經過typeof操做符來判斷基本數據類型(Undefined、Null、Boolean、Number和String),同時相信你們也熟知typeof對於對象的判斷是不許確的,由於特殊值Null被認爲是一個空的對象的引用。javascript

對於數組的建立,可使用構造函數,經過傳遞數量java

var colors = new Array(3);

也能夠在構造函數中傳遞值來建立數組數組

var colors = new Array('red', 'blue', 'green');

建立數組的第二種基本方法是使用數組字面量瀏覽器

var colors = ['red', 'blue', 'green'];

判斷一個對象是否爲數組,最早想到的就是instanceof操做符,經過判斷對象是否爲Array的實例來達到目的安全

var array = [];
console.log(array instanceof Array); // true

使用instanceof操做符的問題在於它假定只有一個全局執行環境。函數

然而這在某些特殊環境下並不安全,下面引用自MDN:prototype

在瀏覽器中,咱們的腳本可能須要在多個窗口之間進行交互。多個窗口意味着多個全局環境,不一樣的全局環境擁有不一樣的全局對象,從而擁有不一樣的內置類型構造函數。這可能會引起一些問題。好比,表達式 [] instanceof window.frames[0].Array 會返回false,由於Array.prototype !== window.frames[0].Array.prototypecode

所以,須要另尋別的方法來判斷。對象

你們知道在任何值上調用Object原生的toString()方法,都會返回一個[object NativeConstructorName]格式的字符串。繼承

var colors = [];
console.log(Object.prototype.toString.call(colors)); // "[object Array]"

利用這一點咱們能夠進一步將其封裝成一個通用函數

function isArray(value) {
  return Object.prototype.toString.call(value).slice(8, -1) === 'Array';
}

在ES5中,爲了解決這個問題,提供了Array.isArray()方法來肯定某個值究竟是不是數組,而無論它是在哪一個全局做用域中建立的。

var colors = [];
console.log(Array.isArray(colors)); // true

行文到此應該結束了,由於判斷數組的方法其實沒有什麼好說的。可是在ES6中,因爲增長了一種新數據類型Symbol,並經過Symbol暴露了一些內部操做,致使了在判斷的結果上會出現一些不肯定狀況。

和本文相關的一個是Symbol.hasInstance方法,它是執行操做符instanceof時內部調用的方法,用於檢測對象的繼承信息。當咱們調用colors instanceof Array時,實際上調用的是Array[Symbol.hasInstance](colors)

若是沒有了解過Symbol的童鞋還不清楚這意味着什麼,且看下面的例子:

var sameArray = {
  [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}

console.log([] instanceof sameArray); // true

這裏咱們定義了sameArrayinstance行爲,內部調用了Array.isArray()方法來判斷傳入的參數是否爲一個數組。一樣咱們能夠改變一個classinstanceof行爲,這裏須要注意一點的是在class中是做爲類的靜態方法。

class Person {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}

最重要的是咱們能夠直接改變內置Array的instanceof行爲,致使其徹底不可靠。

var colors = [];
Object.defineProperty(Array, Symbol.hasInstance, {
  value(v) {
    return false;
  }
})
console.log(colors instanceof Array); // false
console.log(Array.isArray(colors)); // true

上面咱們提到使用Object原生的toString()方法來判斷值是否爲數組的實例。這在ES5中是一個頗有效的方式,但在ES6中咱們一樣能夠經過Symbol.toStringTag來改變Object.prototype.toString()的默認值。

Array.prototype[Symbol.toStringTag] = 'Magic';
var colors = [];
console.log(Object.prototype.toString.call(colors)); // "[object Magic]"

這也意味着Object.prototype.toString()不是一個十分可靠的識別對象類型的方式。

注意:雖然語言自己不會阻止你使用Symbol.toStringTag屬性來改變對象內建的toString()方法的默認值,但仍是不建議這樣作。

最後:不管是在ES5仍是ES6中,最可靠和最安全的數組判斷方法是使用原生的Array.isArray()方法,而在ES3中咱們能夠直接使用Object.prototype.toString()來達到數組識別的目的。

相關文章
相關標籤/搜索