如果你不是台灣的國民,就不能在台灣投票,對吧?
Javascript 是弱型別語言,也因為這個特性,在處理資料時 JavaScript 很可能的很好心,一不小心就把資料自動轉型成另一個資料型態了,所以為了避免在使用陣列內建方法或處理陣列時出現錯誤,常常會使用許多方法來判別是否為陣列。如果元素不是陣列,就無法使用陣列專用的函式或做些陣列的處理,因此才會有確認某元素的原型是陣列的需要。
陣列 Array 在 JavaScript 裡的型別是object
,這點可以透過 typeof 這個運算符回傳的資訊,來確認某一資料是否為陣列。但是,在物件裡的某一元素是否為陣列,又該怎麼判別? 以下有幾種方法:
這邊有四個同是陣列,但不同形態內容的元素,還有一個非陣列的物件變數,我們可以拿它們來測試。
// 陣列常値 // 數字陣列
const arr1 = [1, 2, 3];
// 非同型陣列
const arr2 = ["one", 2, "three"];
// 陣列裡有陣列
const arr3 = [
[1, 2, 3],
["one", 2, "three"]
];
// 非同型陣列
const arr4 = [
{ name : "Tsuifei",
type : "object",
luckyNumber : [5, 7, 13, 42]
},
[
{ name: "Philippe", type: "object" },
{ name: "Ayda", type: "object" },
],
1,
function too() { return "array can contain function too" },
"three",
];
// 物件
const me = { name : "Tsuifei",
type : "object",
luckyNumber : [5, 7, 13, 42]
}
最簡單的陣列判斷語法 isArray,用的是內建Array物件中的isArray,是個ES5的標準方法:Array.isArray(variable)
Array.isArray(arr1); // true
Array.isArray(arr2); // true
Array.isArray(arr3); // true
Array.isArray(arr4); // true
Array.isArray(me); //false
使用constructor
,這個是在Chrome瀏覽器中效能最佳的判斷方法,它是直接用物件的建構式來判斷:variable.constructor === Array
arr1.constructor === Array; // true
arr2.constructor === Array; // true
arr3.constructor === Array; // true
arr4.constructor === Array; // true
me.constructor === Array; // false
與上方一個相同,只是針對物件中的陣列來使用,如果要判別物件中的其中屬性是否為陣列,可以先判斷這個屬性是否存在,再繼續判斷這個值是否為陣列,我們以物件型態的變數來測驗,如下:variable.value && variable.value.constructor === Array
const me = {
name : "Tsuifei",
type : "object",
luckyNumber : [5, 7, 13, 42]
}
me.name && me.name.constructor === Array // false
me.type && me.type.constructor === Array // false
me.luckyNumber && me.luckyNumber.constructor === Array // true
先來看看MDN怎麼解釋:MDN instanceofinstanceof
運算符用於測試建構式函式的prototype屬性,是否出現在物件的原型鏈中的任何位置,也就是說instanceof
運算符是用於判斷是否為某個建構式new
的實例,優點為語法簡潔清楚。
但是缺點還是有的,雖然只要是在原型鏈上面的類別,都會回傳true
,但是建構是有可能因為某些原因而被修改,改變之後的值很有可能不存在於原型鏈上,這時判別回傳得到的值就會成為false
。
function fnuc() {}
let testF = new fnuc;
testF instanceof Array;
// false testF 不是一個陣列,它是一個建構式宣告出來的實例(物件)
instanceof
不只可以判別陣列,也可以拿來判別其他的型別,如string
。
var arr5 = [1,2,3];
arr5 instanceof Array; // true
var arrObj = new Array([1,2,3]);
arrObj instanceof Array; // true
// 也適用於其他型別的判別
var arrObj = new String("hello world");
arrObj instanceof String; // true
instanceof
有個缺點,就是處理的window
或iframe
時的變數會失效,詳細的解說在MDN有較詳細的說明。
==推薦使用==
網路上推薦這種方式判別的頗多,原因應該是這種方式是所有情況都可以正確判別的一種,且可適用各種狀況,也可以判斷陣列以外的其他特別物件,唯一缺點是效率最差。
在JavaScript: The Definitive Guide, 6th Edition 書中有提到,Array.isArray其實就是用這個方式實作的。Object.prototype.toString.call(variable) === '[object Array]'
網路上也有人寫成一支判斷陣列終極解決方案,先用typeof
判別,再確認瀏覽器支不支援這個判別方法,如果不支援,就用另一種方式判別。
const arr6 = [1,2,3];
const arr7 = 42;
function isArrayFn(obj){ // 包成函式
if (typeof Array.isArray === "function") {
return Array.isArray(obj); // 如果瀏覽器支援就用 isArray() 方法
}else{ // 否則就使用 toString 方法
return Object.prototype.toString.call(obj) === "[object Array]";
}
}
isArrayFn(arr6) // true
isArrayFn(arr7) // false
這幾個方式的選擇,網路上的前輩建議是==只要學最後一種==就行了(就是最後一種),可以正確判斷並應用在各種情況為首要條件,有時候正確性比效能快更為重要,更何況它其實是萬用的,除了陣列之外也可以用於其它的判斷情況。雖然它的語法對初學者來說,可能無法在此時完全理解 在說我嗎?,不過就先知道要這樣用就行了。
寫完才發現這篇更詳細的介紹,有興趣的可以轉台過去看,真的很詳細,推~