所以我有一个函数需要检查参数是否是对象,但这失败了,因为:
typeof [] // returns 'object'
这是一个经典的 javascript 陷阱,但我不记得该怎么做才能真正接受对象,但不接受数组。
尝试这样的事情:
obj.constructor.toString().indexOf("Array") != -1
或者(更好)
obj instanceof Array
测试某物是否是 Array 的实例:
const arr = [1,2,3];
Array.isArray(arr); // true
要测试的是某个东西是Object的实例:
const obj = { 1: 'a', 2: 'b', 3: 'c' };
obj?.constructor === Object; // true
所有这些建议您检查(以某种方式)对象是否是“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-稳健类型检查/
为了确定给定对象是否是数组,ECMAScript 5 引入了 Array.isArray() 方法,目前所有现代浏览器都支持该方法。请参阅此ECMAScript兼容性表。
要确定特定对象的类,可以使用 Object.prototype.toString() 方法。
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
不管怎样,下面是 jQuery 如何检查某物是否是数组:
isArray: function( arr ) {
return !!arr && arr.constructor == Array;
}
但是,这篇文章建议这样做:
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
你试过这个吗:
var test = [];
if(test instanceof Array) {
...
}
编辑:此方法在多帧 DOM 环境中不起作用(“typeof”被认为无用 - 或如何编写健壮的类型检查)。 (来自Pointy)
有几个答案,其中大多数都是正确的。我想重新编译:
确保它不是数组:
assert(typeof myVar === 'object' && !Array.isArray(myVar), 'myVar should be an object and not array');
但是Map、Set和其他系统迭代对象呢?我们可以这样测试,并确保它不是一个迭代对象。
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 ...');
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 示例 同样
请使用
Object.prototype.toString.call({}).slice(8,-1)==="Object"
这适用于所有数据类型,您可以替换调用函数内的参数,并且还可以通过比较来检查不同的数据类型。它也适用于空检查