JavaScript 对象检测:点语法与“in”关键字
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7174748/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaScript object detection: dot syntax versus 'in' keyword
提问by Nicholas Shanks
I have seen two ways of detecting whether a UA implements a specific JS property: if(object.property)
and if('property' in object)
.
我见过两种检测 UA 是否实现特定 JS 属性的方法:if(object.property)
和if('property' in object)
.
I would like to hear opinions on which is better, and most importantly, why. Is one unequivocally better than the other? Are there more than just these two ways to do object property detection? Please cover browser support, pitfalls, execution speed, and such like, rather than aesthetics.
我想听听关于哪个更好的意见,最重要的是,为什么。一个明显优于另一个吗?除了这两种方法可以进行对象属性检测吗?请涵盖浏览器支持、陷阱、执行速度等,而不是美学。
Edit:Readers are encouraged to run the tests at jsperf.com/object-detection
编辑:鼓励读者在jsperf.com/object-detection上运行测试
回答by pimvdb
if(object.property)
will fail in cases it is not set (which is what you want), andin cases it has been set to some falsey value, e.g.
undefined
,null
,0
etc (which is not what you want).var object = {property: 0}; if(object.isNotSet) { ... } // will not run if(object.property) { ... } // will not run
if('property' in object)
is slightly better, since it will actually return whether the object reallyhas the property, not just by looking at its value.
var object = {property: 0}; if('property' in object) { ... } // will run if('toString' in object) { ... } // will also run; from prototype
if(object.hasOwnProperty('property'))
is even better, since it will allow you to distinguish between instance properties and prototype properties.
var object = {property: 0}; if(object.hasOwnProperty('property')) { ... } // will run if(object.hasOwnProperty('toString')) { ... } // will not run
if(object.property)
将在未设置的情况下失败(这是你想要的),并在情况下,它已经被设置为一些falsey值,例如
undefined
,null
,0
等(这是不是你想要的)。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
I would say performance is not that big of an issue here, unless you're checking thousands of time a second but in that case you should consider another code structure. All of these functions/syntaxes are supported by recent browsers, hasOwnProperty
has been around for a long time, too.
我会说性能在这里不是什么大问题,除非您每秒检查数千次,但在这种情况下,您应该考虑另一种代码结构。最近的浏览器都支持所有这些函数/语法,hasOwnProperty
并且已经存在很长时间了。
Edit:You can also make a general function to check for existence of a property by passing anything (even things that are not objects) as an object like this:
编辑:您还可以通过将任何东西(甚至不是对象的东西)作为这样的对象传递来创建一个通用函数来检查属性是否存在:
function has(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
Now this works:
现在这有效:
has(window, 'setTimeout'); // true
even if window.hasOwnProperty === undefined
(which is the case in IE version 8 or lower).
即使window.hasOwnProperty === undefined
(在 IE 版本 8 或更低版本中就是这种情况)。
回答by Tim Down
It really depends what you want to achieve. Are you talking about host objects (such as window
and DOM nodes)? If so, the safest check is typeof
, which works for all host objects I know of:
这实际上取决于您想要实现的目标。您是在谈论主机对象(例如window
和 DOM 节点)吗?如果是这样,最安全的检查是typeof
,它适用于我知道的所有主机对象:
if (typeof object.property != "undefined") { ... }
Notes:
笔记:
- Avoid
object.hasOwnProperty()
for host objects, because host objects are not obliged to inherit fromObject.prototype
and therefore may not have ahasOwnProperty()
method (and indeed in IE < 9, they generally do not). - A simple Boolean coercion (e.g.
if (object.property) { ... }
) is a poor test of the existence of a property, since it will give false negatives for falsy values. For example, for an empty textarea,if (textarea.selectionStart) { ... }
will not execute the block even though the property exists. Also, some host object properties throw an error in older versions of IE when attempting to coerce to a Boolean (e.g.var xhr = new ActiveXObject("Microsoft.XMLHTTP"); if (xhr.responseXML) { ... }
). - The
in
operatoris a better test of the existence of a property, but there are once again no guarantees about support for it in host objects. - I recommend against considering performance for this kind of task. Choose the safest option for your project and only optimize later. There will almost certainly be much better candidates for optimization than property existence checks.
- 避免
object.hasOwnProperty()
用于宿主对象,因为宿主对象没有义务继承Object.prototype
,因此可能没有hasOwnProperty()
方法(实际上在 IE < 9 中,它们通常没有)。 - 简单的布尔强制转换(例如
if (object.property) { ... }
)是对属性存在性的糟糕测试,因为它会为假值提供假阴性。例如,对于一个空的 textarea,if (textarea.selectionStart) { ... }
即使该属性存在,也不会执行该块。此外,当尝试强制转换为布尔值(例如var xhr = new ActiveXObject("Microsoft.XMLHTTP"); if (xhr.responseXML) { ... }
)时,某些宿主对象属性会在旧版本的 IE 中引发错误。 - 该
in
操作是一个属性的存在的一个更好的测试,但再次没有关于主机对象对它的支持保障。 - 我建议不要考虑此类任务的性能。为您的项目选择最安全的选项,然后再进行优化。几乎肯定会有比属性存在检查更好的优化候选者。
For more background on this, I recommend this excellent article by Peter Michaux.
有关这方面的更多背景信息,我推荐Peter Michaux 这篇出色的文章。
回答by Ben Lee
Definitely if ('property' in object)
is the right way to go. That actually tests if the property is in the object (or in its prototype chain, more on that below).
绝对if ('property' in object)
是正确的方法。这实际上测试属性是否在对象中(或在其原型链中,更多内容见下文)。
if (object.property)
on the other hand, will coerce 'property' into a truth/flase value. If the property is unset, it will return "undefined", which will be coerced into false, and appear to work. But this will also fail for a number of other set values of properties. javascript is notoriously inconsistent in what it treats as truthy and falsy.
if (object.property)
另一方面,会将“财产”强制转换为真值/闪光值。如果未设置该属性,它将返回“未定义”,这将被强制为 false,并且似乎可以正常工作。但是对于许多其他属性设置值,这也将失败。众所周知,javascript 在将其视为真和假方面不一致。
Finally, like I said above, 'property' in 'object'
will return true if it's in anywhere in the prototype chain. If you want to test that's on the object itself, and not somewhere higher up in the chain, you use the hasOwnProperty
method like so:
最后,就像我上面说的,'property' in 'object'
如果它在原型链的任何地方,就会返回 true。如果你想在对象本身上测试它,而不是在链中更高的某个地方,你可以使用这样的hasOwnProperty
方法:
if (object.hasOwnProperty('property')) ...
回答by Alxandr
The first one would fail if "property" is false of 0. To make sure that there actually exist a property you need to check that object.property !== undefined
, or use the in-keyword.
如果“property”为 0,则第一个将失败。要确保确实存在某个属性,您需要检查该属性object.property !== undefined
,或使用 in 关键字。
[Edit]
[编辑]
There is also the hasOwnProperty-function, but I've never really used that one so I can't say much about it. Though I think it won't return true if the property is set in a prototype, which sometimes you want, other times you don't want.
还有hasOwnProperty-function,但我从来没有真正使用过那个,所以我不能说太多。虽然我认为如果属性设置在原型中,它不会返回 true,有时你想要,有时你不想要。
回答by Fordi
This allows you to use window.hasOwnProperty as either referring to itself or something else, regardless of your scripting host.
这允许您将 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');