鉴于自语言开始以来JavaScript
的发展,为什么没有内置方法来检查对象是否是普通对象?
或者该方法实际存在吗?
答案 0 :(得分:5)
您可以通过以下方式检查对象的类型和实例:
var a = new Date();
console.log(typeof a);
console.log(a instanceof Date);
var b = "Hello";
console.log(typeof b);
console.log(b instanceof Date);
根据OP的评论
更新:
let arr = [1, 2, true, 4, {
"abc": 123
},
6, 7, {
"def": 456
},
9, [10], {}, "[object Object]"
];
arr.forEach(function(v) {
if (typeof v == "object" && !(v instanceof Array) && v != null)
console.log("Object Found");
else
; // console.log("Na");
});
以上代码片段输出三次Object Found
。
答案 1 :(得分:4)
不存在任何明确的直接方法来检查值是否为对象,即属于对象类型,但有一些万无一失的方法可以做到这一点。 I wrote a list in another answer,最简洁似乎
function isObject(value) {
return Object(value) === value;
}
在es escucuss上多次请求过这样的功能。例如,
Juriy Zaytsev" kangax"想知道一个正确的方法来检查一个值是否是一个对象。
事实上,Object.isObject
was proposed as strawman和it appeared in an ES6 early draft。
TC39 bashing:讨论ES6草案中的Object.isObject
。
How primitive are Symbols? Bignums? etc:讨论x === Object(x)
Object.isObject
稻草人最终被拒绝并从ES6草案中删除。
最近,
Object.isObject
现在有is{Type} Methods第0阶段提案,其中包括许多其他检查中的Object.isObject
。
所以仍有希望,最终我们可能会有这样的事情。
以上是一般的测试对象。如果你不想要你应该定义什么"普通对象"适合你。
例如,您可以测试constructor
属性。但任何对象都可以自定义它。
您可以使用Object.prototype.toString
获取旧版ES5 [[Class]]。但任何对象都可以通过Symbol.toStringTag
自定义。
您可以检查[[GetPrototypeOf]]返回的值。但即使是异国情调的对象也可能允许将原型更改为任意对象或null。而Proxy对象甚至可以完全控制该内部方法。
所以很可能你不能依靠这些测试。在标准中添加一些东西可能很难,因为不同的人可能想要不同的东西。
我想要的是检查对象是否是普通对象的某种方式。也就是说,它具有必须由所有对象支持的基本内部方法的默认行为。
一旦你知道一个对象是普通的,你就可以依赖[[GetPrototypeOf]]之类的东西来根据自己的喜好自定义测试。
答案 2 :(得分:3)
依赖[object Object]
字符串表示是不准确的。对于具有以下内容的任何对象,可能会更改此行为:
let o = { toString: () => '...' };
('' + o) !== '[object Object]'
var a = [];
a.toString = () => '[object Object]';
('' + a) === '[object Object]';
检查值是否为普通对象的最可靠方法是
let o = {}
Object.getPrototypeOf(o) === Object.prototype
考虑到constructor
属性未被篡改,检查值是否为普通对象的最直接方法是
let o = {}
o.constructor === Object
这涵盖了从Object
构建的所有POJO,并且不涵盖Object.create(null, { ... })
或任何子类(包括内置插件,如RegExp
或Array
):< / p>
Object.create(null).constructor !== Object
[].constructor !== Object
(new class {}).constructor !== Object
没有专用方法来检查对象简单性的一个可能原因是因为仅使用{}
个对象的限制是不切实际的。这在JS的上下文中没有多大意义。这可以防止使用任何类实例或相对简单的&#39;对象(Object.create({}, ...)
)。
这需要hack才能让所需的非普通对象通过检查:
Object.assign({}, (new class {})).constructor === Object
在大多数对象检查的情况下,允许一切不被禁止的东西&#39;原则得到回报(对infamous null
inconsistency)格外谨慎。
将上述内容应用于this case,过滤非数组对象的安全简洁条件是
o && typeof o === 'object' && !Array.isArray(o)
过滤非内置对象(函数,Array
,RegExp
等)的条件是
o && (o.constructor === Object || !/\[native code\]/.test(o.constructor))
答案 3 :(得分:1)
只是为了进一步记录不同的方式:
我能想到的一种方式:
JSON.stringify(testValue)[0] === '{';
请记住,带有循环引用的对象不能被字符串化。但是,如果确定所有testValues都不能具有循环引用,则可以使用自己的方法来检查Null,Arrays和任何原始值,以确保您拥有Object。
我建议,如果您打算在整个代码中使用它,请定义一个实际实现它的辅助函数,以防万一您发现它无法按预期工作并最终不得不更改检查方式它。
答案 4 :(得分:-1)
每一件JavaScript都是一个Object,因此不需要有一个isObject api