JavaScript对象检测:点语法与'in'关键字
JavaScript object detection: dot syntax versus 'in' keyword
我已经看到了两种检测UA是否实现特定JS属性的方法:if(object.property)
和if('property' in object)
。
我想听听关于哪个更好的意见,最重要的是,为什么。一个肯定比另一个好吗?除了这两种方法之外,还有其他方法可以进行对象属性检测吗?请讨论浏览器支持、陷阱、执行速度等问题,而不是美观问题。
编辑:鼓励读者在jsperf.com/object-detection
if(object.property)
在没有设置的情况下会失败(这是你想要的),和在它被设置为一些假值的情况下,例如
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
我想说性能在这里不是一个大问题,除非你每秒检查数千次,但在这种情况下你应该考虑另一种代码结构。最近的浏览器都支持所有这些函数/语法,hasOwnProperty
也已经存在很长时间了。
Edit:您还可以创建一个通用函数,通过传递任何东西(甚至不是对象的东西)作为对象来检查属性是否存在,就像这样:
function has(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
has(window, 'setTimeout'); // true
即使是window.hasOwnProperty === undefined
(这是IE版本8或更低版本的情况)。
这取决于你想要达到什么效果。您谈论的是主机对象(如window
和DOM节点)吗?如果是这样,最安全的检查是typeof
,它适用于我所知道的所有主机对象:
if (typeof object.property != "undefined") { ... }
指出:
- 避免主机对象的
object.hasOwnProperty()
,因为主机对象没有义务继承Object.prototype
,因此可能没有hasOwnProperty()
方法(在IE <</li> - 一个简单的布尔强制(例如
if (object.property) { ... }
)是一个很差的测试属性的存在,因为它会给假值假阴性。例如,对于一个空的textarea,即使该属性存在,if (textarea.selectionStart) { ... }
也不会执行该块。此外,在旧版本的IE中,当尝试强制转换为布尔值(例如var xhr = new ActiveXObject("Microsoft.XMLHTTP"); if (xhr.responseXML) { ... }
)时,一些主机对象属性会抛出错误。 -
in
操作符是一个更好的测试属性是否存在的方法,但是同样不能保证宿主对象中支持它。 - 我建议不要考虑这种任务的性能。为您的项目选择最安全的选项,然后再进行优化。几乎肯定会有比属性存在性检查更好的优化候选。
关于这方面的更多背景,我推荐Peter Michaux的这篇优秀的文章。
if ('property' in object)
绝对是正确的选择。它实际上测试属性是否在对象中(或在它的原型链中,后面会详细介绍)。
if (object.property)
将强制'property'为true/flase值。如果该属性未设置,它将返回"undefined",该值将被强制为false,并且看起来有效。但是,对于许多其他属性的集合值,这也将失败。Javascript在判断真假方面是出了名的不一致。
最后,就像我上面说的,如果'property' in 'object'
在原型链的任何地方,它将返回true。如果你想在对象本身上测试,而不是在链的更高位置,你可以使用hasOwnProperty
方法,像这样:
if (object.hasOwnProperty('property')) ...
如果"property"为false或0,第一个将失败。要确保确实存在一个属性,您需要检查object.property !== undefined
,或者使用in关键字。
[编辑]
还有hasOwnProperty-function,但我从来没有真正使用过那个,所以我不能说太多关于它。虽然我认为如果属性是在原型中设置的它不会返回true,有时你想要,有时你不想要。
这允许您使用窗口。无论你的脚本主机是什么,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');
- 使用“;这个“;JavaScript原型方法中的关键字
- Node.js's Buffer.writeFloatBE in Javascript
- delete关键字在全局变量上的不同行为
- Setting default onclick behavior for <img> tag in gene
- Lucene Search in Alfresco
- JavaScript 中的嵌套函数和 “this” 关键字
- grep in JQuery to C#
- write HTML in JavaScript
- jQuery setTimeOut: in for-loop
- SetTimeout and clearTimeout in Javascript
- lightbox in html 5 and javascript
- 如何在不使用 new 关键字的情况下从函数创建对象
- Angularjs使用“;这个“;promise内的关键字回调
- 重写需要javascript中带有import关键字的语法
- HTMLInputElement in IE7
- Mongodb$in以与数组中相同的顺序获取结果
- element.dataset in Internet Explorer
- 使用“in”关键字检查 0 始终返回 true
- JavaScript对象检测:点语法与'in'关键字
- 使用"in"迭代Javascript数组关键字