JavaScript學習筆記:檢測數組方法

來源:互聯網
上載者:User

標籤:dom   語言   console   告訴   mat   null   lan   自身   []   

很多時候我們需要對JavaScript中資料類型( Function 、 String 、 Number 、 Undefined 、 Boolean 和 Object )做判斷。在JavaScript中提供了typeof操作符可以對這些常用的資料類型做判斷。但要使用typeof來判斷資料是不是一個數組,就不起作用了。那在實際生產中要如何來檢測資料是不是一個數組呢?

今天的學習任務就是如何來檢測一個資料是不是數組?

typeof操作符

 typeof 可以解決大部分資料類型的檢測,如:

 1 console.log(typeof function () {return;}); // function 2 console.log(typeof "a"); // string 3 console.log(typeof 123); // number 4 console.log(typeof a); //undefined 5 console.log(typeof true); // boolean 6 console.log(typeof NaN); // number 7 console.log(typeof !NaN); //boolean 8 console.log(typeof {name:"大漠",age: "37"}); // object 9 console.log(typeof ["大漠","37"]); // object10 console.log(typeof null); // object

上面的程式碼範例告訴我們,typeof {name:"大漠",age: "37"}和typeof ["大漠","37"]返回的都是object。事實再次證明typeof沒辦法對數組進行檢測,那麼這裡引出一個問題?如何判斷資料是個數群組類型?

檢測數組方法

雖然typeof操作符無法檢測數組,但事實上檢測數組方法有很多種。@Tom、@John、@Rick、@Ken和@Eric在Quora的一篇文章中總結了五種不同的檢測數組的方法。接下來我們一起來瞭解和學習這幾種檢測數組的方法。

ECMAScript 5的isArray函數
1 function isArray(obj) {2     return Array.isArray(obj);3 }4 var arr = ["大漠","w3cplus"]; //建立一個數組5 isArray(arr); // true

毫無疑問,這看起來最完美的解決方案,因為他是原生的。ECMAScript 5將Array.isArray()引入JavaScript。但其相容性令你會感到些許的失望:IE9+、 Firefox 4+、Safari 5+、Opera 10.5+和Chrome都實現了這個方法,但是在IE8之前的版本是不支援的。

在這個基礎上對建構函式做一下檢測,而且這個檢測過程非常的快,而且也非常的準確。事實上對我們的使用太準確了。但在工作是不能確定一個變數是繼承自一個數組。這樣一來,在某種程度上對建構函式做檢測對於我們自己來說是很需要的,也是非常有益的:

1 function isArray(obj) {2     return (typeof obj !== ‘undefined‘ && obj && obj.constructor === Array);3 }
對象自身的constructor屬性

上面的樣本中,檢測建構函式時使用了對像自身的constructor屬性。其實constructor屬性返回一個指向建立了該對象原型的函數引用。使用該屬性也可以檢測數群組類型。

1 var arr = ["大漠","W3cplus"];2 console.log(arr.constructor === Array); // true
instanceof操作符

除了使用對像自身的 constructor 屬性檢測一個數組之外,還可以使用 instanceof 操作符來檢測一個數組。

instanceof 操作符可以用來判斷某個建構函式的  prototype  屬性是否存在另外一個要檢測對象的原型鏈上。也就是判斷instanceof前面的對象是否是後面的類或對象的執行個體。

註:這個操作符和JavaScript中物件導向有點關係,瞭解這個就先得瞭解JavaScript中的物件導向。

來回憶下 instanceof 運算子的使用方式。a instanceof b,如果返回 true,表示 a 是 b 的一個執行個體。那麼如果 a instanceof Array 返回 true,是不是就說明 a 是 數群組類型呢?

1 var arr = ["大漠","W3cplus"];2 console.log(arr instanceof Array); // true
跨frame執行個體化對象帶來的問題

 constructor 和 instanceof 貌似很好的兩個檢測數組的方法,但實際上還是有些漏洞的,當你在多個frame中回來跳的時候,這兩種方法就慘了。由於每一個frame都有自己的一套執行環境,跨frame執行個體化的對象彼此並不共用原型鏈,通過instanceof操作符和constructor屬性檢測的方法自然會失敗。

1 // 建立iframe並添加到DOM中2 var iframe = document.createElement(‘iframe‘); //建立iframe3 document.body.appendChild(iframe); //將建立的iframe添加到body中4 otherArray = window.frames[window.frames.length - 1].Array;5 var arr = new otherArray("大漠","W3cplus"); //聲明數組["大漠","W3cplus"]6 console.log(arr instanceof Array);        // false7 console.log(arr.constructor === Array);   // false
對象原生toString檢測

 Object.prototype.toString 的行為:首先,取得對象的一個內部屬性 [[Class]] ,然後依據這個屬性,返回一個類似於 "[object Array]" 的字串作為結果(看過ECMA標準的應該都知道,[[]]用來表示語言內部用到的、外部不可直接存取的屬性,稱為“內部屬性”)。利用這 個方法,再配合call,我們可以取得任何對象的內部屬性 [[Class]] ,然後把類型檢測轉化為字串比較,以達到我們的目的。

1 isArray = function(obj) {2     return Object.prototype.toString.call(obj) == "[object Array]";3 }4 var arr = ["大漠","W3cplus"];5 console.log(isArray(arr)); // true

 call 改變 toString 的this引用為待檢測的對象,返回此對象的字串表示,然後對比此字串是否是 [object Array] ,以判斷其是否是Array的執行個體。為什麼不直接o.toString()?嗯,雖然Array繼承自Object,也會有toString方法,但是這個方法有可能會被改寫而達不到我們的要求,而 Object.prototype 則是老虎的屁股,很少有人敢去碰它的,所以能一定程度保證其“純潔性”:)

JavaScript 標準文檔中定義: [[Class]] 的值只可能是下面字串中的一個:Arguments, Array, Boolean, Date,Error, Function, JSON, Math, Number, Object, RegExp, String。

其它方法

除了上面介紹的一些檢測數組的方法之外,還有:

@Rick Waldron提供的:

 1 var arr = [1,2,3]; 2 function isArray( arg ) { 3   if ( typeof arg === "object" &&  4      ( "join" in arg && typeof arg.join === "function" ) && 5      ( "length" in arg && typeof arg.length === "number" ) ) { 6         return true; 7   } 8   return false; 9 }10 console.log(true, isArray(arr)); // true true11 console.log(false, isArray({join: true}) ); // false false12 console.log(false, isArray({join: function () {return false;}}) ); // false false

@Shamasis Bhattacharya 提供的:

 1 var isArray = function (subj) { 2     try { 3         subj && (subj.length = -1); 4         return false; 5     } 6     catch (er) { 7         return true; 8     } 9 };10 var arr = [1,2,3];11 isArray(arr); // true

道格拉斯提供的:

1 var is_array = function (value) {2     return value &&3         typeof value === ‘object‘ &&4         typeof value.length === ‘number‘ &&5         typeof value.splice === ‘function‘ &&6         !(value.propertyIsEnumerable(‘length‘));7 };8 var arr = [1,2,3];9 is_array(arr); // true
最佳檢測方法

其實也沒有什麼是最佳檢測方法,只有最合適的檢測方法。綜合上面各種檢測數組的方法,稍做一些處理:

 1 var isArray = (function () { 2     if (Array.isArray) { 3         return Array.isArray; 4     }  5     var objectToStringFn = Object.prototype.toString, 6         arrayToStringResult = objectToStringFn.call([]);  7  8     return function (subject) { 9         return objectToStringFn.call(subject) === arrayToStringResult;10     };11 }());12 13 var arr = [];14 isArray(arr); // true

最佳化的方法就是不管Array.isArray‘是否能用,都可以回到對象原生toString檢測和對象原生toString`檢測上。

 

JavaScript學習筆記:檢測數組方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.