在 JS 中檢查變量是否為數組的多種方式,并說說 ES6 引入檢查數組的緣起!
下面的代碼片段用于檢查變量或值是否為數組。在主流的瀏覽器可以使用Array.isArray方法。對于較舊的瀏覽器,可以使用polyfill
- const variable = ['🍝', '🍜', '🍲'];
- // 主流瀏覽器
- Array.isArray(variable);
- // 老式瀏覽器
- Object.prototype.toString.call(variable) === '[object Array]';
檢查數組的現代方法
檢查數組的最佳方法是使用內置的Array.isArray()
- Array.isArray([]); // true
- Array.isArray(['🍝']); // true
- Array.isArray(new Array('🍝')); // true
瀏覽器支持
瀏覽器對 Array.isArray()的支持非常好
適用于舊版瀏覽器的 Polyfill
如果需要讓較早的瀏覽器支持,則可以使用此MDN polyfill。
- if (!Array.isArray) {
- Array.isArray = function(org) {
- return Object.prototype.toString.call(org) === '[object Array]'
- }
- }
其它方式:使用 Lodash 或 Underscore
如果你使用的是外部庫,它們也有一些內置方法??
Lodash
檢查值是否為數組對象。
- const array = ['🍝', '🍜', '🍲'];
- const notArray = 'not array';
- _.isArray(array); // true
- _.isArray(notArray); // false
Underscore
如果對象是數組,返回 true。
- const array = ['🍝', '🍜', '🍲'];
- const notArray = 'not array';
- _.isArray(array); // true
- _.isArray(notArray); // false
為什么我們不能使用typeof?
通常,我們要檢查值的類型,我們只需使用 typeof
- typeof 'string'; // 'string'
- typeof 100; // 'number'
- typeof true; // 'boolean'
- typeof false; // 'boolean'
- typeof function() {}; // 'function'
- typeof {}; // 'object'
- typeof []; // 'object' <-- 😱
問題是數組實際上處于 Object 數據類型的保護傘之下。所以typeof 返回值是沒問題。不幸的是,這對我們并沒有什么幫助,因為我們只想檢查值是不是數組。
typeof
Type | 例子 | 返回值 |
---|---|---|
String | typeof "hello" | "string" |
Boolean | typeof true typeof false |
"boolean" |
Number | typeof 100 | "number" |
Undefined | typeof undefined | "undefined" |
Function | typeof function() {} | "function" |
Null | typeof null | "object" |
非基本類型 | typeof {} typeof [] |
"object" |
基本類型
在 JS 中有 6 種基本數據類型
- string
- number
- bigint
- boolean
- undefined
- symbol
非基本類型 (對象)
對象是指包含數據和使用數據的指令的數據結構。它們是通過引用存儲的
我比較喜歡稱它為“非基本類型 ”,但它們被稱為Object。
- object
- array
- function
盡管當我們在函數上使用typeof來檢查函數的類型,它返回“ function”,但實際上它是一個對象。
》 MDN:盡管每個 Function 構造函數都是從 Object 構造函數派生的,但它是Function的特殊簡寫形式。
代碼診斷
我收到了很多開發都提供用來檢查Array的不同解決方案。乍一看,它們似乎是不錯的解決方案。有點遺憾的是,有些問題或極端情況使它們不理想。
Array.length 的問題
- const array = ['🍝', '🍜', '🍲'];
- array.length; // 3
如果數組有長度,我們可以假設它是數組?
遺憾的是,此解決方案的問題在于還有其他具有長度即即的數據類型,如:字符串。因此,這可能導致誤報。
- const string = 'not array';
- string.length; // 9
即使一個對象也可以有length屬性:
- const object = { length: 2 };
- const array = ['🍝', '🍜', '🍲'];
- typeof array === 'object' && Boolean(array.length); // true
- typeof object === 'object' && Boolean(object.length); // true <-- 😱
instanceof 的問題
- const array = ['🍝', '🍜', '🍲'];
- array instanceof Array; // true
這種方法在 ES5 很常見, 在許多情況下,這種可以很好的工作。但是,這有一個陷阱!它不適用于多個上下文(例如 框架 或windows)。因為每個框架在其自己的執行環境中都有不同的作用域。因此,它具有不同的全局對象和不同的構造函數。因此,如果嘗試針對該框架的上下文測試數組,則該數組不會返回true,而會錯誤地返回false。
window.frames: frames[] 是窗口中所有命名的框架組成的數組。這個數組的每個元素都是一個Window對象,對應于窗口中的一個框架。
- const frameNode = document.createElement('iframe'); // 創建一個iframe元素節點
- document.body.appendChild(frameNode);
- // 從我們當前的窗口訪問框架
- const frameBrowser = window.frames[window.frames.length - 1];
- // 訪問我們創建的框架的“數組”對象
- frameArray = frameBrowser.Array;
- // 在我們的框架環境中創建一個新的數組
- const newFrameArray = new frameArray('🍝', '🍜', '🍲');
- newFrameArray instanceof Array; // ❌ false
- Array.isArray(newFrameArray); // ✅ true
構造函數的問題
- const array = ['🍝', '🍜', '🍲'];
- array.constructor === Array; // true
這是另一個很好的解決方案。不幸的是,這和instanceof有同樣的問題。它也不能在多個上下文中工作。
- // ...
- newFrameArray.constructor === Array; // ❌ false
- Array.isArray(newFrameArray); // ✅ true
作者:Samantha Ming 譯者:前端小智 來源:medium
原文:https://www.samanthaming.com/tidbits/89-how-to-check-if-variable-is-array/
本文轉載自微信公眾號「大遷世界」,可以通過以下二維碼關注。轉載本文請聯系大遷世界公眾號。