[1]typeof [2]instanceof [3]toString [4]isArray ...
前面的話
對於確定某個對象是不是數組,一直是數組的一個經典問題。本文專門將該問題擇出來,介紹什麼才是正確的javascript數組檢測方式
typeof
首先,使用最常用的類型檢測工具——typeof運算符
var arr = [1,2,3]; console.log(typeof arr);//'object'
前面已經介紹過,數組的本質是一種特殊的對象,所以返回'object'。typeof運算符只能用來區分原始類型和對象類型,對於更具體的對象類型是無法鑒別出來的
instanceof
這時,該instanceof運算符出場了,instanceof運算符用來判斷一個對象是否是特定構造函數的實例
var arr = [1,2,3]; console.log(arr instanceof Array);//true var str = '123'; console.log(str instanceof Array);//false
看上去很實用。但,這時就引出了數組檢測的經典場景——網頁中包含多個框架
【1】先創建一個父網頁box.html和子網頁in.html,其中父網頁通過iframe包含子網頁
//子網頁為空 //父網頁 <iframe name="child" src="in.html"></iframe>
【2】測試父網頁和子網頁的通信,註意一定要在伺服器環境下測試
//子網頁 var arr = [1,2,3]; //父網頁 window.onload = function(){ console.log(child.window.arr);// [1,2,3] }
【3】測試成功,這時進行數組檢測
//子網頁 var arr = [1,2,3]; //父網頁 function test(arr){ return arr instanceof Array; } window.onload = function(){ console.log(child.window.arr);// [1,2,3] console.log(test(child.window.arr));//false }
測試後發現,數組檢測的結果是false。這是因為網頁中包含多個框架,那實際上就存在多個不同的全局環境,從而存在不同版本的Array構造函數。如果從一個框架向另一個框架傳入一個數組,那麼傳入的數組與在第二個框架中原生創建的數組分別具有各自不同的構造函數
toString
typeof操作符在這裡幫不上忙,而instanceof操作符只能用於簡單的情形,這時就需要祭出大殺器——toString(),通過引用Object的toString()方法來檢查對象的類屬性,對數組而言該屬性的值總是"Array"
var arr = [1,2,3]; console.log(Object.prototype.toString.call(arr) === '[object Array]');//true
或者,可以自定義類型識別函數
function type(obj){ return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase(); } var arr = [1,2,3]; console.log(type(arr));//'array'
在多框架環境中測試,同樣返回'array'
//子網頁 var arr = [1,2,3]; //父網頁 function test(arr){ return arr instanceof Array; } function type(obj){ return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase(); } window.onload = function(){ console.log(child.window.arr);// [1,2,3] console.log(test(child.window.arr));//false console.log(type(child.window.arr));//'array' }
isArray
為了讓數組檢測更方便,ECMAScript5新增了Array.isArray()方法。該方法的目的是最終確定某個值到底是不是數組,而不管它在哪個全局環境中創建的
var arr = [1,2,3]; console.log(Array.isArray([]));//true console.log(Array.isArray({}));//false console.log(Array.isArray(arr));//true
在多框架環境中測試,同樣返回true
//子網頁 var arr = [1,2,3]; //父網頁 console.log(Array.isArray(child.window.arr));//true
完整測試代碼
【子網頁(in.html)】
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> var arr = [1,2,3]; </script> </body> </html>
【父網頁(box.html)】
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <iframe name="child" src="in.html"></iframe> <script> function test(arr){ return arr instanceof Array; } function type(obj){ return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase(); } window.onload = function(){ console.log(child.window.arr);// [1,2,3] console.log(test(child.window.arr));//false console.log(type(child.window.arr));//'array' console.log(Array.isArray(child.window.arr));//true } </script> </body> </html>