我一直在做从不同的浏览器不同的库的isPlainObject功能一些测试。
有上宽范围的对象的被测试4种不同的(代码明智)isPlainObject功能:
- jQuery的
- lodash
- 工具(即我工作的一个库)
- 替代方案,建议在下面的评论
对铬v23.0.1271.95上面显示差异这四个通过Chrome浏览器v25.0.1364.160,火狐v 19.0的歌剧v12.14,但效用至少给假为这些对象上所有的浏览器相同的反应
上的jsfiddle测试时,在Chrome上运行
Failed to agree: JSON - jquery: true - utility: false - lodash: true - alt: false
Failed to agree: Math - jquery: true - utility: false - lodash: true - alt: false
Failed to agree: top - jquery: false - utility: false - lodash: true - alt: true
Failed to agree: parent - jquery: false - utility: false - lodash: true - alt: true
编辑:我相信所有的程序都使用类似如下标准 :
jQuery的状态
检查以查看是否一个对象是一个普通的对象(使用创建“{}”或“新对象”)。
lodash状态
检查是否一个给定的值是由对象构造创建的对象。
据我所知,主机对象是不一样的,通过使用构造的对象“{}”或“新对象”,所以我想我的问题是:应该主机对象算作普通的对象?
目前,效用是洽,并说他们没有,其他的程序得到不同的结果在不同的浏览器的主机对象。
编辑:结果的准确性是最重要的因素对我来说,性能是次要的考虑因素。
3个库和建议的替代的性能结果可在jsperf
编辑:这是实用程序库功能,所以你不需要通过代码进行搜索。
defineProperty(utility, "isPlainObject", {
value: (function () {
var o = {};
return function (obj) {
try {
return utility.isObject(obj) && getPrototypeOf(obj).isPrototypeOf(o);
} catch (e) {
return false;
}
};
}())
});
所有这三个以上的时上的FireFox v 19.0一个Opera v12.14执行通过测试
不,至少在Opera的小提琴测试失败window.screen
, Math
, JSON
, DOMError
, LSParserFilter
, DOMImplementationLS
, window.opera
, SVGException
和document.implementation
。
这是在Chrome /铬的错误吗?
什么? 不同的函数返回不同的结果? 没有。
并为每个四个对象,都应该正确的结果是什么(所以我可以决定哪些功能是最准确的)?
你如何定义“正确”? 你如何定义“普通对象”?
我相信,所有3个例程使用下列标准:
检查以查看是否一个对象是一个普通的对象(使用创建“{}”或“新对象”)。
这是几乎没有一个有用的标准,因为那些遇到不一致的对象不是“创造” - 它们是主机对象(甚至是原生对象)恰好存在。
然而,我们可以比较这些功能使用的标准:
jQuery是很奇怪; 你可以阅读它在github上的源代码 。 简而言之:一个对象或功能,其[[类]]是没有一个Boolean Number String Function Array Date RegExp Error
,具有不是truthy nodeName
属性,其具有不是一个window
指向其自身属性,并且不具有constructor
财产或者其prototype
的财产constructor
有一个自己的isPrototypeOf
财产。
他们似乎对跨浏览器支持这样做,但你可以看到它在某些情况下失败,你将有它预期不是一个普通的对象。
效用是有点模糊,但检查本身是简单的:一个对象,其[[类]]是Object
,其原型为Object.prototype
(或者更确切地说,它的原型具有isPrototypeOf
其产生方法true
为{}
Lodash有一些古怪像jQuery,但并不难-你可以阅读在github上源 。 它对于对象类型和非空首先检查,然后得到Object.prototype
经由getPrototypeOf(getPrototypeOf(…))
从一个valueOf
方法,如果它的存在。 如果它发现一个,无论是对象还是其原型一定是Object.prototype
的对象,它不能是Arguments
对象。 如果它没有找到一个,它回落到垫片这我不打算在这里解释。
所有这些事情完成,以支持从不同的环境检测纯对象(例如I帧)与不同Object.prototype
对象并在浏览器中,不提供一个getPrototypeOf
方法。
“ 选择 ”执行:这测试对象的原型为任一null
(但不包括显式Object.prototype
)或为Object.prototype
和[[类]]值为Object
。
应主持人的对象算作普通的对象?
也许。 它总是取决于你的使用情况?
喜欢它的行为是由创建new Object
然后,只需getPrototypeOf(obj) == Object.prototype
应罚款(如果你不需要支持跨框架对象)。 在Math
和JSON
对象将满足这一要求。
对原型无干扰枚举的属性
然后,你还可以允许getPrototypeOf(obj) == null
甚至手动检查枚举的属性,如lodash一样。 现在,这将包括Object.prototype
作为一个“普通对象”为例。
可创建的new Object
然后还加了检查[[类]为Object
,以排除像本地对象JSON
, Math
, Arguments
和所有主机对象与具体实现类。 你真的希望那些在测试函数传递isPlainObject
,他们会造成破坏,如果他们通过了其他检查?
另见你说什么? 在niftysnippets.org (由TJCrowder博客)
文章来源: Should host objects be counted as plain objects in an isPlainObject function?