在 JavaScript 里,
Object和Array都是十分常用的数据类型。不过,在某些情形下,你需要精确判断一个变量究竟是Object还是Array。接下来,我们会详细介绍几种区分它们的方法,同时探讨每种方法的优缺点。
方法一:使用 Array.isArray() 方法
原理
Array.isArray() 是 JavaScript 原生提供的方法,其用途是判断一个值是否为数组。它的语法十分简单:Array.isArray(obj),这里的 obj 就是要检测的对象。要是 obj 是数组,该方法会返回 true,反之则返回 false。
const arr = [1, 2, 3];
const obj = { a: 1, b: 2 };
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
优缺点
- 优点:简洁高效,是原生方法,性能表现良好。
- 缺点:没有明显缺点,是判断数组的首选方法。
方法二:使用 instanceof 操作符
原理
instanceof 操作符用于检测构造函数的 prototype 属性是否存在于某个实例对象的原型链上。使用方式为 obj instanceof Array,若 obj 的原型链里包含 Array.prototype,就会返回 true,这意味着 obj 是数组;反之则返回 false。
const arr = [1, 2, 3];
const obj = { a: 1, b: 2 };
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
优缺点
- 优点:语法直观,易于理解。
- 缺点:在跨
iframe的场景中会出现问题。由于不同iframe有各自的执行上下文和全局对象,不同iframe中的Array构造函数是不一样的,所以这种方式可能会返回错误结果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<iframe id="myIframe"></iframe>
<script>
const iframe = document.getElementById('myIframe');
iframe.onload = function () {
const arrInIframe = iframe.contentWindow.Array(1, 2, 3);
console.log(arrInIframe instanceof Array);
};
</script>
</body>
</html>
在上述代码中,由于 arrInIframe 是在 iframe 中创建的,它的 Array 构造函数和主窗口的 Array 构造函数不同,所以 instanceof 判断可能会出错。
方法三:使用 Object.prototype.toString.call() 方法
原理
这是一种比较可靠的跨环境判断方式。该方法会返回一个表示对象类型的字符串。通过 Object.prototype.toString.call(obj) 能够获取 obj 的内部类型标签。对于数组,该方法会返回 [object Array],而对于普通对象则返回 [object Object]。所以可以通过比较返回的字符串来判断对象是否为数组,即 Object.prototype.toString.call(obj) === '[object Array]'。
const arr = [1, 2, 3];
const obj = { a: 1, b: 2 };
console.log(Object.prototype.toString.call(arr) === '[object Array]');
console.log(Object.prototype.toString.call(obj) === '[object Array]');
优缺点
- 优点:不受跨
iframe等复杂环境的影响,能准确判断对象类型。 - 缺点:代码相对复杂,没有
Array.isArray()简洁。
方法四:检查 constructor 属性
原理
在 JavaScript 中,每个对象都有一个 constructor 属性,这个属性指向创建该对象的构造函数。
对于数组来说,由 Array 构造函数创建的数组对象,其 constructor 属性会指向 Array 构造函数本身。所以可以通过检查对象的 constructor 属性是否等于 Array 来判断该对象是否为数组。如果 arr.constructor === Array 的结果为 true,则表明 arr 是由 Array 构造函数创建的,即 arr 是数组;反之,如果结果为 false,则 arr 不是数组。
const arr = [1, 2, 3];
const obj = { a: 1, b: 2 };
console.log(arr.constructor === Array);
console.log(obj.constructor === Array);
优缺点
-
优点:简单直接。
-
缺点:对象的
constructor属性可以被手动修改,一旦原型被篡改,这种判断方式就可能不准确。
const arr = [1, 2, 3];
arr.constructor = Object;
console.log(arr.constructor === Array);
在上述代码中,手动修改了 arr 的 constructor 属性,导致判断结果出错。
总结
- 若要判断一个对象是否为数组,优先推荐使用
Array.isArray()方法,因为它简洁高效且没有明显缺点。 - 在不涉及跨
iframe场景时,instanceof操作符也是一个不错的选择,其语法直观易懂。 - 若需要在跨
iframe等复杂环境中判断对象类型,Object.prototype.toString.call()方法更为可靠。 - 不建议使用检查
constructor属性的方法,因为它容易受到原型篡改的影响。