如何检查一个对象是否不是数组?

问题描述 投票:0回答:10

所以我有一个函数需要检查参数是否是对象,但这失败了,因为:

typeof [] // returns 'object'

这是一个经典的 javascript 陷阱,但我不记得该怎么做才能真正接受对象,但不接受数组。

javascript types typeof
10个回答
59
投票

尝试这样的事情:

obj.constructor.toString().indexOf("Array") != -1

或者(更好)

obj instanceof Array

24
投票

测试某物是否是 Array 的实例:

const arr = [1,2,3];
Array.isArray(arr);  // true

要测试的是某个东西是Object的实例:

const obj = { 1: 'a', 2: 'b', 3: 'c' };
obj?.constructor === Object;  // true

23
投票

所有这些建议您检查(以某种方式)对象是否是“Array”类的实例(即由“Array”构造)的答案实际上都不是安全的解决方案。它们有时会起作用,也许大多数时候都会起作用,但所有主要框架都已经放弃了这种方法。当多个窗口(通常是一个父窗口和一个或多个框架或 iframe 窗口)之间存在交互时,它的主要问题之一就会出现。如果将一个窗口中创建的数组对象传递到另一个窗口中驻留的 API,则所有这些测试都将失败。为什么?因为您要测试的是一个对象是否是“Array”类的实例在您的本地窗口上下文中。换句话说,当您在

中引用“Array”时
if (myobject instanceof Array) { ... }

当然,您所引用的是

window.Array
。那么,在另一个窗口中构造的数组不会将成为您窗口中 Array 类的实例!

检查构造函数名称可能更安全一些,尽管它仍然有风险。在我看来,你最好采用鸭子打字方法。也就是说,不要问“这是一个数组吗?”相反,你可以问“这个对象似乎支持我在这种情况下需要的某些特定的数组 API 集吗?”例如,“这个对象有

length
属性吗?” Javascript 是一种相当“软”的语言,几乎所有东西都是可变的。因此,即使你确实发现某些东西是由“数组”构造的,你仍然真的不确定你可以用它做什么或对它做什么。

[编辑]感谢该链接,@Lachlan - 这是对问题的非常清晰的描述:http://juhukinners.com/2009/01/11/typeof-considered-useless-or-how-to-write-稳健类型检查/


11
投票

为了确定给定对象是否是数组,ECMAScript 5 引入了 Array.isArray() 方法,目前所有现代浏览器都支持该方法。请参阅此ECMAScript兼容性表

要确定特定对象的类,可以使用 Object.prototype.toString() 方法。

Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"


5
投票

不管怎样,下面是 jQuery 如何检查某物是否是数组:

isArray: function( arr ) {
    return !!arr && arr.constructor == Array;
}

但是,这篇文章建议这样做:

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

2
投票

你试过这个吗:

var test = [];
if(test instanceof Array) {
 ...
}

编辑:此方法在多帧 DOM 环境中不起作用(“typeof”被认为无用 - 或如何编写健壮的类型检查)。 (来自Pointy


1
投票

有几个答案,其中大多数都是正确的。我想重新编译:

确保它不是数组:

assert(typeof myVar === 'object' && !Array.isArray(myVar), 'myVar should be an object and not array');

但是MapSet和其他系统迭代对象呢?我们可以这样测试,并确保它不是一个迭代对象。

assert(typeof myVar === 'object' && !(Symbol.iterator in myVar), 'myVar should be an object and not iterable');
  • 其中不好的部分是,如果您有自己的带有迭代的自定义类,则此断言将失败

作为替代方案,您可以仅按您期望接收的类(对象)进行过滤:

const approved = [MyClass.constructor.name, MyAnotherClass.constructor.name];
assert(approve.indexOf(myVar.constructor.name) > -1, 'myVar should be one of the ...');

0
投票

看看这个包裹

验证给定对象是否不是旧浏览器的数组

https://www.npmjs.com/package/notisarray


0
投票

var obj = {first: 'Stack', last: 'Overflow'};
// var obj = ['Stack', 'overflow']; //You can uncomment this line and comment the above to check..

if(Object.prototype.toString.call(obj) !== '[object Array]') {
    //your code..
    var str = '';
    for(var k in obj) {
    	str = str + obj[k] + ' ';
    }
    console.log('I love ', str);
    alert('I love ' + str);
} else {
	console.log('Could not process. Probably an array');
  alert('Could not process. Probably an array');
}

console.log('Length is: ', Object.keys(obj).length);
alert('Length is: ' + Object.keys(obj).length);

input
Array
Object

检查对象是否为

Array

if(Object.prototype.toString.call(input) === '[object Array]') {}

检查对象是否为

Object

if(Object.prototype.toString.call(input) === '[object Object]') {}


请注意

Object.keys(input).length
将返回数组和对象的长度。

JS Fiddle 示例 同样


0
投票

请使用

Object.prototype.toString.call({}).slice(8,-1)==="Object"
这适用于所有数据类型,您可以替换调用函数内的参数,并且还可以通过比较来检查不同的数据类型。它也适用于空检查

© www.soinside.com 2019 - 2024. All rights reserved.