如何在JavaScript中检查对象是否具有特定属性?
考虑以下代码:
x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
//Do this
}
那是最好的做法吗?
如何在JavaScript中检查对象是否具有特定属性?
考虑以下代码:
x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
//Do this
}
那是最好的做法吗?
Object.hasOwn()
Object.hasOwn()
推荐使用,而不是Object.hasOwnProperty()
。因为它适用于使用Object.create(null)
创建的对象和已覆盖继承的hasOwnProperty()
方法的对象。虽然可以通过在外部对象上调用Object.prototype.hasOwnProperty()
来解决这些问题,但Object.hasOwn()
更加直观。
const object1 = {
prop: 'exists'
};
console.log(Object.hasOwn(object1, 'prop'));
// expected output: true
我对已经给出的答案感到非常困惑——其中大部分都是完全错误的。当然,你可以拥有具有未定义、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()
解决方案,但有一个注意点:它无法区分属性同时位于原型和实例上的情况 - 它只是假设它来自原型。您可以根据自己的情况将其调整为更为宽松或严格,但至少这应该更有帮助。var w = opts.w || 100;
这样做即可。但如果您正在开发一个类库之类的东西,可能需要在某些地方深入一些。 - Halil Özgür__proto__
是非标准属性,在一些旧浏览器中不起作用。即使最近加入了Object.getPrototypeOf
,标准仍然规定您不能更改现有对象的原型。 - Matt Brownefor(prop in object)
循环只遍历可枚举属性。然而,prop in object
检查 object
在原型链中是否有属性 prop
,不管它是否可枚举。 - Oriol_.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
正如约翰·雷西格(John Resig)的回答中所指出的那样,现在基本上已经内置了Object.hasOwn
。Lodash/underscore仍然是在Object.hasOwn
不可用的情况下的备选方案。
lodash.has/index.js
也很有启发性,可以了解一个非常流行和值得信赖的库是如何工作的。 - Brian M. Hunt.has(undefined, 'someKey') => false
,而“underscore”会返回“undefined”。 - Brad Parkslodash
作为"又一个"依赖项的人:这是一种相当常见(如果不是最常见)用于此类问题的库。尽情地重新发明轮子吧。 - Priidu Neemre你可以使用这个(但请阅读下面的警告):
var x = {
'key': 1
};
if ('key' in x) {
console.log('has');
}
但是要注意:即使x
是一个空对象,'constructor' in x
也会返回true
- 同样适用于'toString' in x
和许多其他情况。最好使用Object.hasOwn(x, 'key')
。
in
运算符或不使用。还要注意,in
运算符在浏览器上有很好的支持,包括IE 5.5+,Chrome 1.0+,Firefox 1.0+,Safari 3.0+)。https://dev59.com/pXE85IYBdhLWcg3wJQCt - Adrianoin
也会检查原型属性,而 hasOwnProperty
只迭代用户定义的属性。参考文献:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/in - adi518x
中的 'key' in x
可以用于数组。证据:http://stackoverflow.com/questions/33592385/if-0-in-array-is-this-even-legal - CosmoMyzrailGorynych注意:由于严格模式和 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
。这个表达式的意思是当x.attribute
不等于“undefined”时,条件成立。 - Brian M. Hunt(function (undefined) { // undefined is actually undefined here })();
- bgusachif (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';
};
x.hasOwnProperty('toString') === true;
- Joe SimmonsObject.prototype
已经有了一个内置的、正确的 hasOwnProperty()
方法。覆盖它并使用一个不正确的实现是非常糟糕的想法(因为 1. 属性可以有值 undefined
,2. 这样做会给继承属性带来错误的判断)。不正确的答案应该被删除。我不知道在2008年9月(您看到Resig的回答时)是否可以这样做,所以建议现在这样做。 - T.J. Crowder考虑以下 Javascript 对象:
const x = {key: 1};
您可以使用in
运算符检查对象上是否存在属性:console.log("key" in x);
你也可以使用 for - in
循环遍历对象的所有属性,然后检查特定的属性:
for (const prop in x) {
if (prop === "key") {
//Do something
}
}
您必须考虑此对象属性是否可枚举,因为不可枚举的属性不会在 for-in
循环中显示。另外,如果可枚举的属性遮蔽了原型的非枚举属性,则它不会出现在 Internet Explorer 8 及更早版本中。
如果您想要所有实例属性的列表,无论是否可枚举,可以使用
Object.getOwnPropertyNames(x);
这将返回一个对象上存在的所有属性名称的数组。
反射提供了可用于与 JavaScript 对象交互的方法。静态的 Reflect.has()
方法作为函数类似于 in 运算符。
console.log(Reflect.has(x, 'key'));
// expected output: true
console.log(Reflect.has(x, 'key2'));
// expected output: false
console.log(Reflect.has(object1, 'toString'));
// expected output: true
最后,你可以使用 typeof 操作符直接检查对象属性的数据类型:
if (typeof x.key === "undefined") {
console.log("undefined");
}
如果对象上不存在该属性,则返回字符串 undefined。否则,它将返回适当的属性类型。但是请注意,这并不总是检查对象是否具有属性的有效方法,因为您可以将属性设置为undefined,在这种情况下,使用typeof x.key
仍将返回true(即使该键仍然在对象中)。
类似地,您可以通过直接与 Javascript 属性 undefined
进行比较来检查属性是否存在。if (x.key === undefined) {
console.log("undefined");
}
除非在 x 对象上将键值特别设置为 undefined
,否则此方法应该有效。
让我们澄清一些混淆的问题。首先,假设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
将对其返回false,!== undefined
也是如此。然而,for..in
仍然会在枚举中列出它。
总之,没有跨浏览器的方法(因为Internet Explorer不公开__prototype__
)来确定特定标识符未附加到对象或其原型链中的任何内容。
如果你正在寻找一处房产,那么"没有"是不够的。你需要:
if ('prop' in obj) { }
通常情况下,您不需要关心属性是来自原型还是对象。
然而,因为您在示例代码中使用了“key”,看起来您把对象当作哈希表来处理,这时你的回答就有意义了。所有哈希键都将成为对象的属性,您可以避免原型贡献的额外属性。
John Resig的回答非常全面,但我认为它并不清晰,特别是在何时使用“'prop' in obj”方面。
in
运算符在浏览器上有很好的支持,包括IE 5.5+,Chrome 1.0+,Firefox 1.0+,Safari 3.0+
。https://dev59.com/pXE85IYBdhLWcg3wJQCt - Adrianoin
运算符:"它仅适用于 '对象' 的狭义定义,因此必须声明为 {} 或使用构造函数创建,而不接受数组或基元类型。虽然 OP 没有要求,但其他答案提供了更广泛的技术(适用于数组、字符串等)"。 - Adriano用以下代码测试简单对象:
if (obj[x] !== undefined)
如果你不知道对象的类型,使用:
if (obj.hasOwnProperty(x))
所有其他选项的速度都比较慢...
对于在Node.js下执行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: 4.51 s
hasKey2 execution time: 0.90 s
hasKey3 execution time: 0.76 s
hasKey4 execution time: 0.93 s
hasKey5 execution time: 2.15 s
简而言之,如果您的 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'
。
Object.hasOwn
,它解决了Object.prototype.hasOwnProperty
的一些问题。 - Sebastian Simon