本文介绍了是否应该在isPlainObject函数中将宿主对象计为普通对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在不同浏览器上的不同库中对isPlainObject函数进行一些测试.

I've been doing some testing of isPlainObject functions from different libraries on different browsers.

有4种不同(在代码方面)的isPlainObject函数正在广泛的对象上进行测试:

There are 4 different (code wise) isPlainObject functions being tested on a wide range of objects:

  • jquery
  • lodash
  • 实用程序(我正在使用的库)
  • 替代,在下面的评论中建议

以上所有四个在Chrome v23.0.1271.95到Chrome v25.0.1364.160,FireFox v 19.0和Opera v12.14上都显示出差异,但是实用程序至少对所有这些对象给出相同的false响应浏览器

All four of the above show differences on Chrome v23.0.1271.95 through to Chrome v25.0.1364.160, FireFox v 19.0 an Opera v12.14, but utility at least gives the same response of false for these object on all the browsers

在Chrome上运行时在jsfiddle上进行的测试

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

  • true表示例程认为对象是普通对象,而false则不是普通对象
  • 编辑:我相信所有例程都使用以下类似的条件:

    I believe that all routines are using the following similar criteria:

    jquery状态
    检查对象是否为普通对象(使用"{}"或新对象"创建).

    jquery states
    Check to see if an object is a plain object (created using "{}" or "new Object").

    lodash状态
    检查给定值是否是由Object构造函数创建的对象.

    lodash states
    Checks if a given value is an object created by the Object constructor.

    我知道宿主对象与使用"{}"或新对象"构造的对象不同,所以我想我的问题是:宿主对象应该算作普通对象吗?

    I understand that host objects are not the same as objects constructed by using "{}" or "new Object", so I guess my question is: should host objects be counted as plain objects?

    目前,实用程序是一致的,但说不是,其他例程对于不同浏览器上的宿主对象给出不同的结果.

    Presently, utility is consistant and says they are not, the other routines give different results for host objects on different browsers.

    编辑:结果的准确性对我来说是最重要的因素,性能是次要考虑因素.

    Accuracy of the result is the most important factor for me, performance is of secondary consideration.

    jsperf 上提供了这3个库的性能结果和建议的替代方法.

    Performance results of the 3 libraries and the suggested alternative are available on jsperf

    编辑:这是实用程序库功能,因此您无需搜索代码.

    this is the utility library function, so you don't need to search through the code.

    defineProperty(utility, "isPlainObject", {
        value: (function () {
            var o = {};
    
            return function (obj) {
                try {
                    return utility.isObject(obj) && getPrototypeOf(obj).isPrototypeOf(o);
                } catch (e) {
                    return false;
                }
            };
        }())
    });
    

    推荐答案

    否,至少在Opera中,对于window.screenMathJSONDOMErrorLSParserFilterDOMImplementationLSwindow.operaSVGExceptiondocument.implementation.

    No, at least in Opera the tests in the fiddle fail for window.screen, Math, JSON, DOMError, LSParserFilter, DOMImplementationLS, window.opera, SVGException, and document.implementation.

    什么?不同的函数返回不同的结果吗?不.

    What? That different functions return different results? No.

    您如何定义正确"?您如何定义普通对象"?

    How do you defined "correct"? How do you defined "plain object"?

    这不是一个有用的标准,因为您遇到差异的那些对象不是创建的"-它们是恰好存在的宿主对象(甚至是本机对象).

    That's hardly a useful criterion, since those objects where you experience discrepancies are not "created" - they are host objects (or even native objects) that just happen to exist.

    但是,我们可以比较这些功能使用的标准:

    Yet, we could compare which criteria those functions use:

    • jQuery 很奇怪;您可以在github上阅读源代码.简而言之:对象或函数,其[[Class]]不是Boolean Number String Function Array Date RegExp Error的一个,没有真实的nodeName属性,没有指向其自身的window属性,并且没有属性,或者constructorprototype属性具有自己的isPrototypeOf属性.

    • jQuery is very odd; you can read it's source code at github. In short: An object or function, whose [[Class]] is not one of Boolean Number String Function Array Date RegExp Error, that has not a truthy nodeName property, that has not a window property pointing to itself, and that has no constructor property or whose prototype property of the constructor has an own isPrototypeOf property.

    他们似乎是为了跨浏览器支持而这样做的,但是正如您所看到的,在某些情况下,如果您希望它不是一个普通的对象,它就会失败.

    They seem to do this for cross-browser support, but as you can see it fails in some cases where you would have it expected not to be a plain object.

    实用程序有点模糊,但是检查本身很简单:[[Class]]为Object并且原型为Object.prototype的对象(或者,其原型有一个isPrototypeOf方法,对于{}来说,它的结果为true.

    Utility is a bit obfuscated, but the check itself is simple: An object whose [[Class]] is Object and whose prototype is Object.prototype (or rather, whose prototype has a isPrototypeOf method that yields true for {}).

    Lodash 具有jQuery之类的怪异之处,但并不难-您可以阅读来自github的资源.它首先检查对象类型而不是null,然后通过valueOfvalueOf方法获取Object.prototype(如果存在).如果找到一个对象,则该对象或其原​​型必须是该Object.prototype对象,并且不能是Arguments对象.如果找不到,则会退回到 shim 在这里我将不解释.

    Lodash has a few oddities like jQuery, but not that hard - you can read the source at github. It first checks for object type and not null, then gets Object.prototype via getPrototypeOf(getPrototypeOf(…)) from a valueOf method if it exists. If it found one, either the object or its prototype must be that Object.prototype object and it must not be an Arguments object. If it did not found one, it falls back to the shim which I'm not going to explain here.

    完成所有这些操作以支持在不提供getPrototypeOf方法的浏览器中使用不同的Object.prototype对象检测来自不同环境(例如iframe)的普通对象.

    All these things are done to support detecting plain objects from different environments (e.g. iframes) with a different Object.prototype object and in browsers that do not provide a getPrototypeOf method.

    "替代"实现:这将测试对象的原型为null(但明确排除了Object.prototype)还是Object.prototype以及[[Class ]]的值为Object.

    "Alternative" implementation: This tests the prototype of the object to be either null (but explicitly excluding Object.prototype) or to be Object.prototype and the [[Class]] value to be Object.

    也许.它总是取决于您的用例……

    Maybe. It always depends on your use case…

    • 类似于由new Object

    然后getPrototypeOf(obj) == Object.prototype应该没问题(如果不需要支持跨框架对象). MathJSON对象将满足此要求.

    Then just getPrototypeOf(obj) == Object.prototype should be fine (if you don't need to support cross-frame objects). The Math and JSON objects would fulfill this requirement.

    原型上没有可枚举的干扰

    Have no interfering enumerable properties on the prototypes

    然后,您还可以允许getPrototypeOf(obj) == null,甚至可以像lodash一样手动检查可枚举的属性.例如,现在这将包括Object.prototype作为普通对象".

    Then you might also allow getPrototypeOf(obj) == null or even manually check for enumerable properties like lodash does. This would now include Object.prototype as a "plain object" for example.

    可由new Object

    然后还添加[[Class]]为Object的检查,以排除诸如JSONMathArguments之类的本机对象以及所有具有实现特定类的宿主对象.您是否真的希望这些在测试isPlainObject的函数中传递,并且如果通过其他测试,是否会造成破坏?

    Then also add the check for [[Class]] to be Object to exclude native objects like JSON, Math, Arguments and all those host objects with implementation-specific classes. Would you really expect those to be passed in the functions that test isPlainObject, and would they cause havoc if they passed the other tests?

    另请参阅niftysnippets.org上的 说什么? (TJCrowder的博客)

    See also Say what? at niftysnippets.org (blog by T.J.Crowder)

    这篇关于是否应该在isPlainObject函数中将宿主对象计为普通对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 02:45