小技巧:完美地判断变量是不是数组

693 阅读2分钟

对于js中数据路诶性的监测相信大家都不陌生,js中有很多方法可以提供给我们使用

但是有些方法可以用,但不严谨,今天就如何判断变量到底是不是数组来说明一下常用的方法

主流的判断方法 Array.isArray()

最好的方式是用ES的新方法Array.isArray()来判断


Array.isArray([]); // true
Array.isArray(['🍝']); // true
Array.isArray(new Array('🍝')); // true

浏览器支持情况

  • chrome
  • Firfox
  • Safari
  • Edge
  • IE 9

旧浏览器兼容

ES5的数组原型上没有这个方法,所以需要重写Array的原型方法

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
 

或者你可以单独封装一个方法


function isArray(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
}

使用Lodash或者Underscore

我么可以借助第三的js方库来帮我们判断

Lodash

const array = ['🍝', '🍜', '🍲'];
const notArray = 'not array';

_.isArray(array); // true
_.isArray(notArray); // false

Underscore

const array = ['🍝', '🍜', '🍲'];
const notArray = 'not array';

_.isArray(array); // true
_.isArray(notArray); // false

为何不使用typeof

因为 Array 在js中的类型都是object 引用类型

typeof 'string'; // 'string'
typeof 100; // 'number'
typeof true; // 'boolean'
typeof false; // 'boolean'
typeof function() {}; // 'function'
typeof {}; // 'object'

typeof []; // 'object' <-- 😱
 

为何不使用Array.length

const array = ['🍝', '🍜', '🍲'];

array.length; // 3

数组的length属性确实可以帮助我们判断,但是字符串类型的数据也有length属性

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

这是我也看到人们参考的常见解决方案。 老实说,这是一个很好的方法。

但是,这有一个问题! 它不适用于多个上下文(例如框架或窗口)。

因为每一个frame都有不同的作用域,有自己的执行环境。

因此,它具有不同的全局对象和不同的构造函数。

因此,如果您尝试针对该frame的上下文测试数组,它将不会返回 true,而是会错误地返回为 false。

const frameNode = document.createElement('iframe'); // Create an iframe Element Node
document.body.appendChild(frameNode); // Append our frame element
const frameBrowser = window.frames[window.frames.length - 1]; // Access the frame from our current window
frameArray = frameBrowser.Array; // Access the "Array" object of the frame we created

// Create a new Array in our frame environment
const newFrameArray = new frameArray('🍝', '🍜', '🍲');

newFrameArray instanceof Array; // ❌ false

Array.isArray(newFrameArray); // ✅ true


为何不使用constructor

const array = ['🍝', '🍜', '🍲'];

array.constructor === Array; // true

这和instacneof存在同样的问题’

// ...

newFrameArray.constructor === Array; // ❌ false

Array.isArray(newFrameArray); // ✅ true