如何检查对象在JavaScript中是否具有特定属性?
考虑:
x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
//Do this
}
那是最好的方法吗?
in
和hasOwnProperty
出来的方式比别人慢,我(98%速度较慢)。我对hasOwnProperty
变慢并不感到惊讶,但我对此感到惊讶in
。
如何检查对象在JavaScript中是否具有特定属性?
考虑:
x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
//Do this
}
那是最好的方法吗?
in
和hasOwnProperty
出来的方式比别人慢,我(98%速度较慢)。我对hasOwnProperty
变慢并不感到惊讶,但我对此感到惊讶in
。
Answers:
我对所给出的答案感到困惑-他们中的大多数都是完全错误的。当然,您可以拥有具有未定义,空值或假值的对象属性。因此,简单地将属性检查减少到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
,但有一个警告:不能区分原型和实例上具有相同属性的情况-只是假设它来自原型。您可以根据自己的情况将其更改为宽容或严格,但是至少这应该会有所帮助。
var w = opts.w || 100;
。但是,如果您使用某种库,则可能需要在某些地方走得更远。
__proto__
为空?简单IMPL: function hasOwnProperty(obj, prop) { var temp = obj.__proto__; obj.__proto__ = null; var ret = prop in obj; obj.__proto__ = temp; return ret; }
(壳,obj.constructor.prototype
应补充)。
__proto__
是非标准的,在某些较旧的浏览器中不起作用。即使最近添加了Object.getPrototypeOf
该标准,您仍然不能更改现有对象的原型。
for(prop in object)
循环迭代仅枚举的属性。但是,独立于是否可枚举,prop in object
检查object
属性是否prop
在原型链中某个位置。
使用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
npm install lodash.has
公开一个npm模块,而该has
函数只有在最小化时才编译为175个字节。查看并lodash.has/index.js
了解非常受欢迎且值得信赖的库的工作原理也是很有见地的。
lodash
的版本适用本: .has(undefined, 'someKey') => false
虽然underscore
回报undefined
lodash
“又一个”依赖关系的人:对于这种事情,它是一个相当普通的(如果不是最常见的)库。玩转车轮吧。
关于什么?
var x = {'key': 1};
if ('key' in x) {
console.log('has');
}
in
操作或不还要注意的是,in
运营商具有优秀的浏览器支持IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+
stackoverflow.com/questions/2920765/...
in
还检查原型属性,而hasOwnProperty
仅迭代用户定义的属性。参考:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
'key' in x
确实可以处理数组。证明: stackoverflow.com/questions/33592385/...
注意:由于采用严格模式,因此以下内容已过时hasOwnProperty
。正确的解决方案是使用严格模式,并使用来检查属性的存在obj.hasOwnProperty
。这个答案早于这两件事,至少已经广泛实施了(是的,它已经很老了)。将以下内容作为历史记录。
请记住,如果您未使用严格模式,那么undefined
(不幸的)这不是 JavaScript中的保留字。因此,某个人(显然是其他人)可能有重新定义它的宏大想法,从而破坏了您的代码。
因此,一种更可靠的方法如下:
if (typeof(x.attribute) !== 'undefined')
另一方面,这种方法比较冗长,而且速度较慢。:-/
一种常见的方法是,以确保undefined
被实际上未定义,例如,通过将代码置于它接受一个附加的参数的函数,称为undefined
,使不通过的值。为确保未传递值,您可以立即自行调用它,例如:
(function (undefined) {
… your code …
if (x.attribute !== undefined)
… mode code …
})();
void 0
定义了返回规范undefined
,可以x.attribute !== void 0
吗?
(function (undefined) { // undefined is actually undefined here })();
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!');
}
一个更安全,但速度较慢的解决方案,如指出,由康拉德·鲁道夫和阿明Ronacher将是:
Object.prototype.hasOwnProperty = function(property) {
return typeof this[property] !== 'undefined';
};
x.hasOwnProperty('toString') === true;
Object.prototype
已经具有内置的正确的hasOwnProperty
。用不正确的实现覆盖它(1.属性可以具有值undefined
2。这将为继承的属性提供误报)只是一个可怕的坏主意。错误答案可以并且应该删除。当您看到Resig的答案时,我不知道您是否可以在08年9月做得到,所以发表评论建议现在就这样做。
您可以使用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,在这种情况下,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__
)来确定特定标识符尚未附加到对象或其原型链中的任何内容。
如果要搜索属性,则为“ NO”。你要:
if ('prop' in obj) { }
通常,您不必关心该属性是否来自原型或对象。
但是,由于在示例代码中使用了“键”,因此看起来您将对象视为哈希,在这种情况下,您的答案才有意义。所有哈希键都将是对象中的属性,并且可以避免原型带来的额外属性。
John Resig的回答非常全面,但我认为还不清楚。特别是当在obj中使用“ prop”时。
in
运营商具有优秀的浏览器支持IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+
stackoverflow.com/questions/2920765/...
in
运算符的另一条评论中指出的那样:“它在狭义上与'对象'一起工作,因此声明为{}或使用构造函数创建,它不接受数组或基元。不是OP要求它,而是其他一些答案则提出了更为广泛的技术(使用数组,字符串等)”
要测试简单对象,请使用:
if (obj[x] !== undefined)
如果您不知道它是什么对象类型,请使用:
if (obj.hasOwnProperty(x))
所有其他选项都较慢。
细节
在Nodejs下,其他人建议的5个选项下的100,000,000个周期的性能评估:
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])...
它,因为我发现它更具可读性。
玩得开心。
是的,它是:)我想您也可以这样做Object.prototype.hasOwnProperty.call(x, 'key')
,如果x
有一个叫做hasOwnProperty
:) 的属性也应该可以工作
但这会测试自己的属性。如果要检查它是否具有也可以继承的属性,可以使用typeof x.foo != 'undefined'
。
您还可以使用ES6 Reflect
对象:
x = {'key': 1};
Reflect.has( x, 'key'); // returns true
Reflect.has
可在此处找到有关MDN的文档。
静态
Reflect.has()
方法的功能类似于in运算符。
好的,除非您不想继承属性,否则我的答案似乎正确:
if (x.hasOwnProperty('key'))
以下是一些其他选项来包含继承的属性:
if (x.key) // Quick and dirty, but it does the same thing as below.
if (x.key !== undefined)
var x = { key: false };
该x.key
方法将是不正确的。
不要这样做,这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));
另一种相对简单的方法是使用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开始可以安全使用
Object.keys(info).indexOf('someotherthing') !== -1
“ hasOwnProperty”可用于确定对象是否具有指定的属性作为该对象的直接属性;与in运算符不同,此方法不会检查对象的原型链。
因此,最有可能的是,对于您所看到的问题,您不想使用hasOwnProperty,它确定属性是否直接附加到对象本身。
如果要确定该属性是否存在于主要要使用的原型链中,例如:
if( prop in object ){ // do something }
我希望这有帮助。
由于存在大规模投票的风险,因此这是针对特定情况的另一种选择。:)
如果要测试对象上的成员,并且想知道它是否已设置为除以下以外的其他值:
那么您可以使用:
var foo = {};
foo.bar = "Yes, this is a proper value!";
if (!!foo.bar) {
// member is set, do something
}
ECMA Script 6解决方案具有反射功能。创建包装器,如下所示:
/**
Gets an argument from array or object.
The possible outcome:
- If the key exists the value is returned.
- If no key exists the default value is returned.
- If no default value is specified an empty string is returned.
@param obj The object or array to be searched.
@param key The name of the property or key.
@param defVal Optional default version of the command-line parameter [default ""]
@return The default value in case of an error else the found parameter.
*/
function getSafeReflectArg( obj, key, defVal) {
"use strict";
var retVal = (typeof defVal === 'undefined' ? "" : defVal);
if ( Reflect.has( obj, key) ) {
return Reflect.get( obj, key);
}
return retVal;
} // getSafeReflectArg
对象上存在方法“ hasOwnProperty”,但不建议直接调用此方法,因为有时对象可能为null或对象上存在某些属性,例如: { hasOwnProperty: false }
更好的方法是:
// good
var obj = {"bar": "here bar desc"}
console.log(Object.prototype.hasOwnProperty.call(obj, "bar"));
// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
console.log(has.call(obj, "bar"));
您可以使用以下方法-
var obj = {a:1}
console.log('a' in obj) //1
console.log(obj.hasOwnProperty('a')) //2
console.log(Boolean(obj.a)) //3
以下方法之间的区别如下:
var obj = {
a:2,
__proto__ :{b:2}
}
console.log('b' in obj)
console.log(Boolean(obj.b))
var obj = {
a:2,
__proto__ :{b:2}
}
console.log(obj.hasOwnProperty('b'))
var obj = {
b : undefined
}
console.log(Boolean(obj.b))
console.log('b' in obj);
您需要使用方法object.hasOwnProperty(property)
。如果对象具有属性,则返回true,否则返回false。