题 如何检查对象在JavaScript中是否具有属性?


如何检查对象在JavaScript中是否具有属性?

考虑:

x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
    //Do this
}

这是最好的方法吗?


1183
2017-09-25 19:27


起源


我用每个人的答案写了一个jsperf测试,看看哪个是最快的: jsperf.com/dictionary-contains-key - styfle
@styfle非常感谢,jsperf测试帮助了我很多! - Luillyfe


答案:


我对所给出的答案感到困惑 - 其中大多数都是完全不正确的。当然,您可以拥有具有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但有一点需要注意:它无法区分原型和实例上相同属性的情况 - 它只是假设它来自原型。根据你的情况,你可以把它转移到更宽松或更严格的程度,但至少这应该更有帮助。


1203
2017-09-25 21:52



@grantwparks如果您正在构建一个简单的滑块插件并想要检查选项是否存在,那么这可能不仅仅是需要。你可以做点什么 var w = opts.w || 100;。但是如果你是某种类型的图书馆,你可能需要在某些地方走得更远。 - Halil Özgür
@ kralco626:是的,现在我觉得使用hasOwnProperty()非常安全 - 但对于真正安全的跨浏览器解决方案,请选择John的。 - Jacob
关于什么 临时 改变 __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 应该补充)。 - Kasztan
@Kasztan __proto__ 是非标准的,在某些旧版浏览器中不起作用。即使最近增加了 Object.getPrototypeOf 标准说你仍然无法改变现有对象的原型。 - Matt Browne
一个 for(prop in object) loop只迭代可枚举的属性。然而, prop in object 检查是否 object 有财产 prop 在原型链中的某个地方,独立于它是否可以枚举。 - Oriol


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

235
2017-07-03 17:01



我猜它是因为“添加这个库”很少是一个流行的解决方案,即使问题是关于复杂的DOM操作,答案是“go use jQuery”。 - Winfield Trail
我明白你的意思了,@不得,谢谢。顺便说一句,如果一个人反对包括整个lodash库,那么可以编译子组件或 npm install lodash.has 它只暴露了一个npm模块 has 缩小时编译为175字节的函数。看看这个也很有见地 lodash.has/index.js 了解一个非常受欢迎和值得信赖的图书馆如何运作 - Brian M. Hunt
和 lodash的版本适用于此: .has(undefined, 'someKey') => false 而 underscore 回报 undefined - Brad Parks
对每个抱怨添加的人 lodash 作为“又一个”依赖:对于这类事情来说,它是一个相当常见的(如果不是最常见的)库。玩得开心重新发明轮子。 - Priidu Neemre
即使你想重新发明轮子,检查现有的轮子也不是一个坏主意。 - wolfdawn


注意:由于严格模式,以下现在基本上已经过时了 hasOwnProperty。正确的解决方案是使用严格模式并使用检查属性的存在 obj.hasOwnProperty。这个答案  这两件事,至少同样广泛实施(是的,它是那么久)。请将以下内容作为历史记录。


请记住 undefined (不幸的是)  如果您没有使用严格模式,则使用JavaScript中的保留字。因此,有人(显然是其他人)可能有重新定义它的宏伟想法,破坏你的代码。

因此,更强大的方法如下:

if (typeof(x.attribute) !== 'undefined')

另一方面,这种方法更冗长,也更慢。 : - /

一种常见的替代方法是确保这一点 undefined 是 其实 未定义,例如将代码放入一个接受附加参数的函数中,调用 undefined,那是没有传递一个值。为了确保它没有传递一个值,你可以立即自己调用它,例如:

(function (undefined) {
    … your code …
    if (x.attribute !== undefined)
        … mode code …
})();

108
2017-09-25 19:48



好奇,因为 void 0 被定义为返回规范 undefined,有人可以 x.attribute !== void 0? - Brian M. Hunt
布莱恩:我不是专家,但这似乎是一种巧妙的方法来实现它。 - Christopher Smith
如果着名的“别人”重新定义了undefined是什么,我认为最好的做法是重写那些代码。 - Oskar Holmkratz
undefined = (function () {}()); if (a.attribute !== undefined) 'foo'; - Joe Simmons
拥有一个可靠的未定义var的最佳方法是在闭包内工作,并具有不匹配的函数签名: (function (undefined) { // undefined is actually undefined here })(); - bgusach


关于什么?

var x = {'key': 1};

if ('key' in x) {
    console.log('has');
}

93
2018-02-02 17:56



需要注意的是,它适用于狭义上的“对象”,因此声明为{}或使用构造函数创建,它不接受数组或基元。并不是说OP需要它,但是其他一些答案提出了更广泛的技术(使用数组,字符串等) - Danubian Sailor
@РСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ感谢你指出这一点(接受的答案没有详细说明为什么要使用 in 操作员与否。还要注意 in 运营商有出色的浏览器支持 IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+  stackoverflow.com/questions/2920765/... - Adrien Be
操作者 in 同时检查原型属性 hasOwnProperty 仅迭代用户定义的属性。参考: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - adi518
'key' in x  做 使用数组。证明: stackoverflow.com/questions/33592385/... - CosmoMyzrailGorynych


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!');
}

一个更安全但更慢的解决方案, 正如所指出的那样 通过 康拉德鲁道夫 和 Armin Ronacher 将会:

Object.prototype.hasOwnProperty = function(property) {
    return typeof this[property] !== 'undefined';
};

35
2017-09-25 19:32



我认为这不够好。 x.hasOwnProperty('toString') === true; - Joe Simmons
不是要求不同意,而是要理解。除了布尔值true或false之外,x.hasOwnProperty会返回任何内容吗?如果没有,发布的代码应该每次都有效。我想也许如果方法被覆盖,但是,除非你知道最重要的方法,否则依赖结果永远不可靠。 - enobrev
我认为我们有误传。我的意思是使用你的方法,它会说'toString'是它自己的属性,但事实并非如此。 - Joe Simmons
Object.prototype 已经内置,正确 hasOwnProperty。用不正确的实现覆盖它(1.属性可以有值 undefined,2。这会给继承属性带来误报)只是一个非常糟糕的主意。可以并且应该删除不正确的答案。我不知道你能不能在08年9月那样做 当你看到Resig的答案时,所以评论建议现在就做。 - T.J. Crowder


你可以使用 in 运算符来检查对象上是否存在属性:

x = {'key': 1};
alert("key" in x);

您还可以使用a循环遍历对象的所有属性 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,在这种情况下,使用 typeof x.key 仍然会返回true(即使键仍在对象中)。

更新:您可以通过与未定义的javascript属性进行比较来检查属性是否存在

if (x.key === undefined) {
    alert("undefined");
}

除非专门设置密钥,否则这应该有效 undefined 在x对象上


30
2018-03-30 06:18



您的更新部分是错误的。请看这里: jsfiddle.net/sbgg04yg - Breaking Benjamin
更新以显示与JavaScript未定义属性进行比较的情况可能会失败 - goonerify


让我们在这里切入一些混乱。首先,让我们通过假设来简化 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__)确定特定标识符尚未附加到对象或其原​​型链中的任何内容。


24
2017-09-26 09:16





如果您正在寻找房产,那么“不”。你要:

if ('prop' in obj) { }

通常,您不应该关心属性是来自原型还是对象。

但是,因为您在示例代码中使用了“key”,所以看起来您将对象视为哈希,在这种情况下,您的答案是有意义的。所有哈希键都是对象中的属性,并且您可以避免原型提供的额外属性。

John Resig的回答非常全面,但我认为还不清楚。特别是何时在obj中使用“'prop'”。


15
2018-05-21 15:57



请注意 in 运营商有出色的浏览器支持 IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+  stackoverflow.com/questions/2920765/... - Adrien Be
正如另一条关于使用的评论所指出的那样 in 运算符:“它在狭义上与'对象'一起使用,因此声明为{}或使用构造函数创建,它不接受数组或基元。不是OP需要它,但是其他一些答案提供了更宽泛的技术(使用数组,字符串等)“ - Adrien Be
评论原因我已经两次没有评论而被投票。但我还是喜欢我的回答。也许这样做的人想要所有方法来测试所有类型的属性的“全面”答案。但我的答案是概念性的,为此,简洁。回复:Adrien Be,一个不可忽视的属性是一个不适合一般用户范围的属性,因此概念上“in”很好;) - Gerard ONeill


是的它是:)我认为你也可以 Object.prototype.hasOwnProperty.call(x, 'key') 哪个也应该有效 x有一个叫做的财产 hasOwnProperty :)

但是那可以测试自己的属性。如果您想检查它是否具有也可以被加入的属性,您可以使用 typeof x.foo != 'undefined'


12
2017-09-25 19:30





if (typeof x.key != "undefined") {

}

因为

if (x.key)

如果失败了 x.key 解决了 false (例如, x.key = "")。


12
2017-09-25 19:39