在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.prototype
。code
所以,須要另尋別的方法來判斷。對象
你們知道在任何值上調用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
這裏咱們定義了sameArray
的instance
行爲,內部調用了Array.isArray()
方法來判斷傳入的參數是否爲一個數組。一樣咱們能夠改變一個class
的instanceof
行爲,這裏須要注意一點的是在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()
來達到數組識別的目的。