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

IT技术 javascript
2021-02-02 02:48:52

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

考虑:

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

这是最好的方法吗?

6个回答

我真的对给出的答案感到困惑 - 其中大多数完全不正确。当然,您可以拥有具有 undefined、null 或 false 值的对象属性。因此,简单地将属性检查减少到typeof this[property]或更糟,x.key会给您带来完全误导的结果。

这取决于你在寻找什么。如果你想知道一个对象是否物理上包含一个属性(并且它不是来自原型链上的某个地方),那么object.hasOwnProperty这就是要走的路。所有现代浏览器都支持它。(旧版本的 Safari 中缺少它 - 2.0.1 及更早版本 - 但这些版本的浏览器很少再使用了。)

如果您正在寻找的是一个对象是否具有可迭代的属性(当您迭代对象的属性时,它会出现),那么 do:prop in object会给您想要的效果。

由于 usinghasOwnProperty可能是您想要的,并且考虑到您可能需要回退方法,因此我向您提供以下解决方案:

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,有一个警告:无法区分原型和实例上的相同属性的情况 - 它只是假设它来自原型。根据您的情况,您可以将其更改为更宽松或更严格,但至少这应该更有帮助。

John Resig 的答案似乎在 IE8 中不起作用,在这个实时演示jsbin.com/tovaburefeva/1/edit?js,output 中看到它失败我认为这是因为hasOwnProperty() "is not supported on host objects for Internet Explorer 8 and below"请参阅msdn.microsoft.com/en-us/library/ie/328kyd6z(v=vs.94).aspx以及stackoverflow.com/questions/8157700/...
2021-03-24 02:48:52
警告:不要in对原语使用检查。
2021-03-25 02:48:52
@Kasztan__proto__是非标准的,在某些旧浏览器中不起作用。即使最近添加Object.getPrototypeOf了标准,您仍然无法更改现有对象的原型。
2021-03-31 02:48:52
@grantwparks 如果您正在构建一个简单的滑块插件并想要检查选项项是否存在,那么这可能确实超出了需要。你可以做类似的事情var w = opts.w || 100;但是,如果您正在使用某种库,则可能需要在某些部分走得更远。
2021-04-03 02:48:52
一个for(prop in object)循环迭代仅枚举的属性。但是,prop in object检查是否在原型链中的某处object具有该属性prop,而与它是否可枚举无关。
2021-04-06 02:48:52

随着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
即使你想重新发明轮子,检查现有的轮子也不是一个坏主意。
2021-03-10 02:48:52
我明白你的意思,@sudowned,谢谢。顺便说一句,如果人们不喜欢包含整个 lodash 库,则可以编译子组件或npm install lodash.has公开一个 npm module,该module仅具有一个has在缩小时可编译到 175 字节函数。lodash.has/index.js查看一个非常受欢迎和值得信赖的库是如何工作的也是很有见地的
2021-03-12 02:48:52
我猜这是因为“添加这个库”很少是一个流行的解决方案,即使问题是关于复杂的 DOM 操作并且答案是“去使用 jQuery”。
2021-03-17 02:48:52
对于每个抱怨添加lodash“又一个”依赖项的人:对于这类事情,它是一个相当常见(如果不是最常见的)库。玩得开心重新发明轮子。
2021-03-17 02:48:52
andlodash的版本适用于此: .has(undefined, 'someKey') => falsewhileunderscore返回undefined
2021-04-02 02:48:52

用:

var x = {
  'key': 1
};

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

请注意,它适用于狭义的“对象”,因此声明为 {} 或使用构造函数创建,它不接受数组或原语。并不是 OP 需要它,而是其他一些答案提供了更广泛的技术(使用数组、字符串等)
2021-03-12 02:48:52
@РСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ感谢您指出这一点(已接受的答案没有详细说明为什么应该使用该in运算符。另请注意,该in运算符具有出色的浏览器支持IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+ stackoverflow.com/25/questions
2021-03-23 02:48:52
Operatorin还检查原型属性,而hasOwnProperty仅迭代用户定义的属性。参考:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-03-29 02:48:52
'key' in x 使用数组。证明: stackoverflow.com/questions/33592385/...
2021-04-09 02:48:52

注意:由于严格模式和hasOwnProperty. 正确的解决方案是使用严格模式并使用obj.hasOwnProperty. 这个答案早于这两件事,至少在广泛实施之前(是的,它是那么古老)。将以下内容作为历史记录。


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

因此,更稳健的方法如下:

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

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

一种常见的方法是,以确保undefined实际上未定义,例如,通过将代码置于它接受一个附加的参数的函数,称为undefined,使不通过的值。为确保它没有传递值,您可以立即自己调用它,例如:

(function (undefined) {
    … your code …
    if (x.attribute !== undefined)
        … mode code …
})();
最好有一个可靠的未定义 var,是在一个闭包中工作,并有一个无与伦比的函数签名: (function (undefined) { // undefined is actually undefined here })();
2021-03-28 02:48:52
@evanrmurphy 不要使用它,它已经过时了(请参阅我回答开头的注释)。
2021-03-31 02:48:52
如果著名的“其他人”重新定义了 undefined 是什么,我认为最好的做法是重写该代码。
2021-04-04 02:48:52
只是好奇,既然void 0被定义为返回规范undefined,可以做x.attribute !== void 0吗?
2021-04-07 02:48:52
布赖恩:我不是专家,但这似乎是一个聪明的方法。
2021-04-09 02:48:52
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 RudolphArmin Ronacher指出的那样一个更安全但更慢的解决方案是:

Object.prototype.hasOwnProperty = function(property) {
    return typeof this[property] !== 'undefined';
};
我认为我们沟通有误。我的意思是使用你的方法,它会说 'toString' 是它自己的属性,但它不是。
2021-03-22 02:48:52
不是要求不同意,而是要理解。除了布尔值 true 或 false 之外,x.hasOwnProperty 是否会返回任何内容?如果没有,发布的代码应该每次都有效。我想也许如果该方法被覆盖,但是除非您知道覆盖方法,否则依赖结果永远不会可靠。
2021-03-26 02:48:52
我认为这还不够好。 x.hasOwnProperty('toString') === true;
2021-04-02 02:48:52
Object.prototype已经有一个内置的,正确的hasOwnProperty. 用不正确的实现覆盖它(1. 属性可以有值undefined,2. 这会给继承的属性带来误报)只是一个可怕的坏主意。不正确的答案可以而且应该被删除。我不知道您是否可以在 08 年 9 月看到 Resig 的回答时做到这一点,因此发表评论以建议现在这样做。
2021-04-05 02:48:52