如何检查对象是否在JavaScript中具有属性?
考虑:
x = {'key': 1}; if ( x.hasOwnProperty('key') ) { //Do this }
这是最好的方法吗?
我对给出的答案感到困惑 - 大多数答案都是完全不正确的.当然,您可以拥有具有undefined,null或false值的对象属性.因此,简单地减少财产检查,typeof this[property]
或者更糟糕的是,x.key
会给你带来完全误导性的结果.
这取决于你在寻找什么.如果你想知道一个对象是否物理上包含一个属性(并且它不是来自原型链上的某个地方),那么object.hasOwnProperty
就是要走的路.所有现代浏览器都支持它.(在旧版本的Safari - 2.0.1及更早版本中缺少它 - 但是这些版本的浏览器很少被使用.)
如果您正在寻找的是一个对象在其上具有可迭代的属性(当您迭代对象的属性时,它将会出现)然后执行:prop in object
将为您提供所需的效果.
由于使用hasOwnProperty
可能是您想要的,并且考虑到您可能需要回退方法,我向您呈现以下解决方案:
var obj = { a: undefined, b: null, c: false }; // a, b, c all found for ( var prop in obj ) { document.writeln( "Object1: " + prop ); } function Class(){ this.a = undefined; this.b = null; this.c = false; } Class.prototype = { a: undefined, b: true, c: true, d: true, e: true }; var obj2 = new Class(); // a, b, c, d, e found for ( var prop in obj2 ) { document.writeln( "Object2: " + prop ); } function hasOwnProperty(obj, prop) { var proto = obj.__proto__ || obj.constructor.prototype; return (prop in obj) && (!(prop in proto) || proto[prop] !== obj[prop]); } if ( Object.prototype.hasOwnProperty ) { var hasOwnProperty = function(obj, prop) { return obj.hasOwnProperty(prop); } } // a, b, c found in modern browsers // b, c found in Safari 2.0.1 and older for ( var prop in obj2 ) { if ( hasOwnProperty(obj2, prop) ) { document.writeln( "Object2 w/ hasOwn: " + prop ); } }
以上是一个有效的跨浏览器解决方案hasOwnProperty
,但有一点需要注意:它无法区分原型和实例上相同属性的情况 - 它只是假设它来自原型.根据你的情况,你可以把它转移到更宽松或更严格的程度,但至少这应该更有帮助.
使用Underscore.js
或(甚至更好)lodash
:
_.has(x, 'key');
哪个调用Object.prototype.hasOwnProperty
,但(a)键入的时间较短,(b)使用"安全引用hasOwnProperty
"(即使它hasOwnProperty
被覆盖也有效).
特别是,lodash定义_.has
为:
function has(object, key) { return object ? hasOwnProperty.call(object, key) : false; } // hasOwnProperty = Object.prototype.hasOwnProperty
注意:由于严格模式,以下现在基本上已经过时了hasOwnProperty
.正确的解决方案是使用严格模式并使用检查属性的存在obj.hasOwnProperty
.这个答案早于这两个方面,至少广泛实施(是的,它是旧的).请将以下内容作为历史记录.
请记住,如果您没有使用严格模式,那么undefined
(遗憾的是)不是 JavaScript中的保留字.因此,某人(显然是其他人)可能会有重新定义它的宏伟想法,破坏您的代码.
因此,更强大的方法如下:
if (typeof(x.attribute) !== 'undefined')
另一方面,这种方法更冗长,也更慢.: - /
一种常见的方法是,以确保undefined
是实际上未定义,例如通过将代码置于它接受一个附加的参数的函数,称为undefined
,使不通过的值.为了确保它没有传递一个值,你可以立即自己调用它,例如:
(function (undefined) { … your code … if (x.attribute !== undefined) … mode code … })();
关于什么?
var x = {'key': 1}; if ('key' in x) { console.log('has'); }
if (x.key !== undefined)
Armin Ronacher似乎已经打败了我,但是:
Object.prototype.hasOwnProperty = function(property) { return this[property] !== undefined; }; x = {'key': 1}; if (x.hasOwnProperty('key')) { alert('have key!'); } if (!x.hasOwnProperty('bar')) { alert('no bar!'); }
如Konrad Rudolph和Armin Ronacher 所指出的那样,更安全但更慢的解决方案是:
Object.prototype.hasOwnProperty = function(property) { return typeof this[property] !== 'undefined'; };
您可以使用in
运算符检查对象上是否存在该属性:
x = {'key': 1}; alert("key" in x);
您还可以使用循环遍历对象的所有属性for - in
,然后检查特定属性:
for (prop in x) { if (prop == "key") { //Do something } }
您必须考虑此对象属性是否可枚举,因为非可枚举属性不会显示在for-in
循环中.此外,如果可枚举属性遮蔽原型的非可枚举属性,则它将不会显示在Internet Explorer 8及更早版本中.
如果您想要所有实例属性的列表,无论是否可枚举,您都可以使用
Object.getOwnPropertyNames(x);
这将返回对象上存在的所有属性的名称数组.
最后,您可以使用typeof运算符直接检查对象属性的数据类型:
if (typeof x.key == "undefined") { alert("undefined"); }
如果对象上不存在该属性,则它将返回字符串undefined.否则它将返回适当的属性类型.但是,请注意,这并不总是检查对象是否具有属性的有效方法,因为您可以将属性设置为undefined,在这种情况下,using typeof x.key
仍将返回true(即使键仍然是在对象中).
更新:您可以通过与未定义的javascript属性进行比较来检查属性是否存在
if (x.key === undefined) { alert("undefined"); }
这应该有效,除非undefined
在x对象上专门设置了键
让我们在这里切入一些困惑.首先,让我们假设hasOwnProperty
已经存在简化; 对于当前使用的绝大多数浏览器来说都是如此.
hasOwnProperty
如果传递给它的属性名称已添加到对象,则返回true.它完全独立于分配给它的实际值,这可能是确切的 undefined
.
因此:
var o = {} o.x = undefined var a = o.hasOwnProperty('x') // a is true var b = o.x === undefined // b is also true
然而:
var o = {} var a = o.hasOwnProperty('x') // a is now false var b = o.x === undefined // b is still true
问题是当原型链中的对象具有值为undefined的属性时会发生什么?hasOwnProperty
对它来说是假的,也是如此!== undefined
.然而,for..in
仍然会在列举中列出它.
底线是没有跨浏览器方式(因为Internet Explorer不公开__prototype__
)以确定特定标识符尚未附加到对象或其原型链中的任何内容.
如果您正在寻找房产,那么"不".你要:
if ('prop' in obj) { }
通常,您不应该关心属性是来自原型还是对象.
但是,因为您在示例代码中使用了"key",所以看起来您将对象视为哈希,在这种情况下,您的答案是有意义的.所有哈希键都是对象中的属性,并且您可以避免原型提供的额外属性.
John Resig的回答非常全面,但我认为还不清楚.尤其是何时在obj中使用"'prop'".
是的它是:)我认为你也可以做Object.prototype.hasOwnProperty.call(x, 'key')
哪个也应该工作,如果x
有一个名为hasOwnProperty
:) 的属性
但是那可以测试自己的属性.如果你想检查它是否有一个也可能被加入的属性你可以使用typeof x.foo != 'undefined'
.
要测试简单对象,请使用:
if (obj[x] !== undefined)
如果您不知道它使用的是哪种对象类型:
if (obj.hasOwnProperty(x))
所有其他选项都比较慢..
细节
在Nodejs下的100,000,000个周期的性能评估到其他人建议的5个选项:
function hasKey1(k,o) { return (x in obj); } function hasKey2(k,o) { return (obj[x]); } function hasKey3(k,o) { return (obj[x] !== undefined); } function hasKey4(k,o) { return (typeof(obj[x]) !== 'undefined'); } function hasKey5(k,o) { return (obj.hasOwnProperty(x)); }
评估告诉我们,除非我们特别想要检查对象的原型链以及对象本身,否则我们不应该使用常见的形式: if (X in Obj)...
根据用例的不同,速度要慢2到6倍
hasKey1 execution time: 4s 510.427785ms hasKey2 execution time: 0s 904.374806ms hasKey3 execution time: 0s 760.336193ms hasKey4 execution time: 0s 935.19901ms hasKey5 execution time: 2s 148.189608ms
最重要的是,如果您的Obj不一定是一个简单的对象,并且您希望避免检查对象的原型链并确保x直接由Obj拥有,请使用'if(obj.hasOwnProperty(x))...'.
否则,当使用简单对象而不担心对象的原型链时,使用if (typeof(obj[x]) !== 'undefined')...
是最安全和最快捷的方式.
如果你使用一个简单的对象作为哈希表并且从不做任何变态,我会使用,if (obj[x])...
因为我觉得它更具可读性.
玩得开心.
您还可以使用ES6 Reflect
对象:
x = {'key': 1}; Reflect.has( x, 'key'); // returns true
有关MDN的文档Reflect.has
可在此处找到.
静态
Reflect.has()
方法的作用类似于in运算符.
if (typeof x.key != "undefined") { }
因为
if (x.key)
如果x.key
解析为false
(例如),则失败x.key = ""
.
好的,看起来我得到了正确的答案,除非你不想要继承的属性:
if (x.hasOwnProperty('key'))
以下是包含继承属性的其他一些选项:
if (x.key) // Quick and dirty, but it does the same thing as below. if (x.key !== undefined)
请勿这样做,这object.hasOwnProperty(key))
确实很糟糕,因为这些方法可能会受到所考虑对象的属性的影响-考虑{ hasOwnProperty: false }
-或该对象可能是空对象(Object.create(null))
。
最好的方法是Object.prototype.hasOwnProperty.call(object, key)
:
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope. /* or */ import has from 'has'; // https://www.npmjs.com/package/has // ... console.log(has.call(object, key));
hasOwnProperty"可用于确定对象是否具有指定属性作为该对象的直接属性; 与in运算符不同,此方法不会检查对象的原型链."
所以最有可能的是,对于你的问题看来,你不想使用hasOwnProperty,它确定属性是否存在直接附加到对象本身,.
如果你想确定你想要使用的原型链中是否存在该属性,例如:
if( prop in object ){ // do something }
我希望这有帮助.
另一种相对简单的方法是使用Object.keys
。这将返回,array
这意味着您可以获得数组的所有功能。
var noInfo = {}; var info = {something: 'data'}; Object.keys(noInfo).length //returns 0 or false Object.keys(info).length //returns 1 or true
尽管我们处在一个强大的浏览器支持中。因为这个问题太老了,所以我想添加一下:从JS v1.8.5开始可以安全使用