什麼才是正確的javascript陣列檢測方式

小火柴的藍色理想發表於2016-07-18

前面的話

  對於確定某個物件是不是陣列,一直是陣列的一個經典問題。本文專門將該問題擇出來,介紹什麼才是正確的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>

  

相關文章