为什么JavaScript中没有内置方法来检查对象是否是普通对象?

时间:2016-11-07 01:18:52

标签: javascript

鉴于自语言开始以来JavaScript的发展,为什么没有内置方法来检查对象是否是普通对象?

或者该方法实际存在吗?

5 个答案:

答案 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上多次请求过这样的功能。例如,

事实上,Object.isObject was proposed as strawmanit appeared in an ES6 early draft

Object.isObject稻草人最终被拒绝并从ES6草案中删除。

最近,

现在有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, { ... })或任何子类(包括内置插件,如RegExpArray):< / 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)

过滤非内置对象(函数,ArrayRegExp等)的条件是

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