JavaScript对象检测:点语法与'in'关键字

时间:2011-08-24 11:33:27

标签: javascript properties

我已经看到了两种检测UA是否实现特定JS属性的方法:if(object.property)if('property' in object)

我想听听哪些更好,更重要的是为什么的意见。一个明显优于另一个吗?是否有不仅仅是这两种方法来进行对象属性检测?请涵盖浏览器支持,陷阱,执行速度等,而不是美学。

修改:鼓励读者在jsperf.com/object-detection

运行测试

5 个答案:

答案 0 :(得分:115)

  • if(object.property)

    如果没有设置(这是你想要的),

    将会失败,会被设置为某些假值,例如undefinednull0等(这不是您想要的)。

    var object = {property: 0};
    if(object.isNotSet) { ... } // will not run
    if(object.property) { ... } // will not run
    
  • if('property' in object)

    略好一些,因为它实际上会返回对象是否具有该属性,而不仅仅是查看其值。

    var object = {property: 0};
    if('property' in object) { ... } // will run
    if('toString' in object) { ... } // will also run; from prototype
    
  • if(object.hasOwnProperty('property'))

    甚至更好,因为它允许您区分实例属性和原型属性。

    var object = {property: 0};
    if(object.hasOwnProperty('property')) { ... } // will run
    if(object.hasOwnProperty('toString')) { ... } // will not run
    

我会说性能在这里不是一个大问题,除非你每秒检查数千次,但在这种情况下你应该考虑另一种代码结构。最近的浏览器支持所有这些功能/语法,hasOwnProperty也已存在很长时间了。


编辑:您还可以通过将任何内容(甚至是非对象的内容)作为对象传递来创建一个通用函数来检查属性是否存在:

function has(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
}

现在可行:

has(window, 'setTimeout'); // true

即使window.hasOwnProperty === undefined(在IE 8或更低版本中就是这种情况)。

答案 1 :(得分:11)

这取决于你想要实现的目标。您是在谈论主机对象(例如window和DOM节点)吗?如果是这样,最安全的检查是typeof,它适用于我所知道的所有主机对象:

 if (typeof object.property != "undefined") { ... }

注意:

  • 避免使用object.hasOwnProperty()主机对象,因为主机对象没有义务从Object.prototype继承,因此可能没有hasOwnProperty()方法(实际上在IE< 9中,它们通常是不要)。
  • 一个简单的布尔强制(例如if (object.property) { ... })是对属性存在的不良测试,因为它会给虚假值假阴性。例如,对于空文本区域,即使属性存在,if (textarea.selectionStart) { ... }也不会执行该块。此外,在尝试强制转换为布尔值(例如var xhr = new ActiveXObject("Microsoft.XMLHTTP"); if (xhr.responseXML) { ... })时,某些主机对象属性会在旧版本的IE中引发错误。
  • in operator是对属性存在的更好测试,但再次无法保证在宿主对象中支持它。
  • 我建议不考虑此类任务的表现。为您的项目选择最安全的选项,并且仅在以后进行优化。几乎可以肯定,优化的候选者比财产存在检查要好得多。

有关此问题的更多背景信息,我建议this excellent article by Peter Michaux

答案 2 :(得分:2)

绝对if ('property' in object)是正确的方法。这实际上测试了属性是否在对象中(或者在其原型链中,更多的是在下面)。

另一方面,

if (object.property)会将“财产”强制转化为真实/ fla值。如果属性未设置,它将返回“undefined”,这将被强制为false,并且似乎有效。但是,对于许多其他属性值,这也将失败。 javascript在它被视为真实和虚假的东西方面是出了名的不一致。

最后,就像我上面所说的那样,'property' in 'object'如果在原型链的任何地方都会返回true。如果你想测试对象本身,而不是链中的某个位置,你可以使用hasOwnProperty方法,如下所示:

if (object.hasOwnProperty('property')) ...

答案 3 :(得分:0)

如果“property”为0,则第一个将失败。要确保实际存在属性,您需要检查object.property !== undefined,或使用in-keyword。

[编辑]

还有hasOwnProperty函数,但我从来没有真正使用过那个,所以我不能说太多。虽然我认为如果属性设置在原型中(有时你想要的话),它会不会返回,有时你不想要它。

答案 4 :(得分:0)

这允许您使用window.hasOwnProperty作为引用自身或其他内容,无论您的脚本主机是什么。

// No enclosing functions here
if (!('hasOwnProperty' in this))
    function hasOwnProperty(obj, prop) {
        var method = Object.prototype.hasOwnProperty;
        if (prop === undefined)
            return method.call(this, obj);
        return method.call(obj, prop);
    }

//Example of use
var global = global || this; //environment-agnostic way to get the global object
var x = 'blah';
WScript.Echo(global.hasOwnProperty('x') ? 'true' : 'false'); //true

//Use as non-object method
var y = { z: false };
WScript.Echo(hasOwnProperty(y, 'z') ? 'true' : 'false'); //true
WScript.Echo(hasOwnProperty(y, 'w') ? 'true' : 'false'); //false

// true ಠ_ಠ
WScript.Echo(hasOwnProperty(global, 'hasOwnProperty') ? 'true' : 'false');