如何在JavaScript中检查对象是否为数组:完整指南
\n\n您是否曾经有过这样的想法:“明明传了一个数组,但代码却报错了”?这种情况很常见。在JavaScript中,数组是对象,简单的typeof检查在这里行不通。今天我们将解析三种主要方法来检查对象是否为数组,并找出在实际项目中应该使用哪一种。
为什么typeof不适用?
\n\n在深入探讨之前,我们先来了解一下为什么新手经常在这里犯错。在JavaScript中,数组是对象的一种特殊情况。因此,对数组使用typeof运算符会返回"object",而不是"array"。您可以自己试试:
const arr = [1, 2, 3];\nconsole.log(typeof arr); // "object" — 毫无用处\n\n此外,typeof null === "object"是语言中一个众所周知的bug,已经无法修复。因此,如果您正在检查来自用户或API的数据,不能依赖typeof。需要更可靠的方法。
方法1:Array.isArray() — 现代标准
\n\n从ES5(2009年)开始,JavaScript内置了Array.isArray()方法。这是检查对象是否为数组最正确、最简单的方法。
const arr = [10, 20, 30];\nconst notArr = { length: 3, 0: 'a', 1: 'b', 2: 'c' };\n\nconsole.log(Array.isArray(arr)); // true\nconsole.log(Array.isArray(notArr)); // false\nconsole.log(Array.isArray('hello')); // false\nconsole.log(Array.isArray(null)); // false\n\n为什么这是最佳选择?因为Array.isArray()即使在多框架场景下也能正确工作:如果数组来自另一个iframe或框架,instanceof可能会失效,但Array.isArray()不会。它检查对象的内部类型[[Class]],而不是原型链。
浏览器支持
\n该方法支持所有现代浏览器,包括Internet Explorer 9+。如果您需要支持非常旧的浏览器(IE 8及以下),请使用polyfill或第三种方法。
\n\n方法2:instanceof Array — 经典方法
\n\ninstanceof运算符检查对象的原型链中是否存在Array.prototype原型。听起来很复杂,但实际上是这样工作的:
const arr = [1, 2, 3];\nconsole.log(arr instanceof Array); // true\n\nconst obj = { a: 1 };\nconsole.log(obj instanceof Array); // false\n\n// 但这里有个意外:\nconst iframeArr = new iframe.contentWindow.Array(1, 2, 3);\nconsole.log(iframeArr instanceof Array); // false! (如果数组来自另一个框架)\n\n问题就在这里:如果您的页面上有多个iframe,或者您在使用Web Workers,来自不同全局上下文的数组具有不同的原型。instanceof没有考虑到这一点,可能会对真正的数组返回false。因此,在现代开发中,最好避免使用instanceof来检查数组。
方法3:Object.prototype.toString.call() — 万能方法
\n\n这种方法在Array.isArray()出现之前被使用。如果您需要编写polyfill或在Array.isArray不可用的环境中工作,它仍然有效。
function isArray(obj) {\n return Object.prototype.toString.call(obj) === '[object Array]';\n}\n\nconsole.log(isArray([1, 2])); // true\nconsole.log(isArray({ a: 1 })); // false\nconsole.log(isArray('string')); // false\nconsole.log(isArray(null)); // false\n\n这是如何工作的?Object.prototype对象的toString方法返回一个类似[object Type]的字符串。对于数组,它始终是[object Array]。这种方法绕过了iframe的问题,因为它检查内部类