ChatGPT解决这个技术问题 Extra ChatGPT

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

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

考虑:

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

这是最好的方法吗?

我用每个人的答案写了一个 jsperf 测试,看看哪个最快:jsperf.com/dictionary-contains-key
(对象中的'propertyName')? '财产在那里' : '财产不在那里'
@styfle 感谢 jsperf 测试。对我来说,inhasOwnProperty 比其他人慢了 方式(慢了 98%)。我对 hasOwnProperty 变慢并不感到惊讶,但我对 in 感到惊讶。
有一个新的第 3 阶段提案 Object.hasOwn,它解决了 Object.prototype.hasOwnProperty 的一些问题。

j
j D3V

2022 更新

与其在 100 万个重复的答案中添加另一个答案,我只想在这里添加评分最高的答案,即截至 2022 年还有另一个选择

Object.hasOwn()

没有必要重新发明轮子,所以我给你[MDN版本][1]:

推荐使用 Object.hasOwn() 而不是 Object.hasOwnProperty(),因为它适用于使用 Object.create(null) 创建的对象以及覆盖了继承的 hasOwnProperty() 方法的对象。虽然可以通过在外部对象上调用 Object.prototype.hasOwnProperty() 来解决这些问题,但 Object.hasOwn() 更直观。

我补充说它在语法上看起来也更干净。

约翰·雷西格的回答:

我真的对给出的答案感到困惑——其中大多数都是完全不正确的。当然,您可以拥有具有 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 的一个有效的跨浏览器解决方案,但有一个警告:它无法区分原型和实例上的相同属性的情况 - 它只是假设它来自原型。您可以根据您的情况将其更改为更宽松或更严格,但至少这应该更有帮助。


@grantwparks 如果您正在构建一个简单的滑块插件并想要检查选项项的存在,那么这可能确实超出了需要。您可以执行 var w = opts.w || 100; 之类的操作。但是,如果您正在研究图书馆之类的东西,则可能需要在某些部分走得更远一些。
@Kasztan __proto__ 是非标准的,在某些较旧的浏览器中不起作用。即使最近添加了 Object.getPrototypeOf,该标准仍表示您仍然无法更改现有对象的原型。
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).aspxstackoverflow.com/questions/8157700/…
for(prop in object) 循环仅迭代可枚举属性。但是,prop in object 会检查 object 在原型链中的某处是否具有属性 prop,这与它是否可枚举无关。
警告词:不要对原语使用 in 检查。
x
xxx

使用 Underscore.js 或 (even better) 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

我猜这是因为“添加这个库”很少是一个流行的解决方案,即使问题是关于复杂的 DOM 操作并且答案是“去使用 jQuery”。
我明白你的意思,@sudown,谢谢。顺便说一句,如果不想包含整个 lodash 库,可以编译子组件或 npm install lodash.has,它公开了一个 npm 模块,其中只有一个 has 函数,在缩小时编译到 175 字节。查看 lodash.has/index.js 以了解一个非常受欢迎和值得信赖的库是如何工作的,这也很有见地。
lodash 的版本适用于此:.has(undefined, 'someKey') => falseunderscore 返回 undefined
对于每个抱怨将 lodash 添加为“又一个”依赖项的人:对于这类事情,它是一个相当常见的(如果不是最常见的)库。玩得开心重新发明轮子。
即使您想重新发明轮子,检查现有的轮子也不是一个坏主意。
l
leonheess

利用:

var x = {'key': 1 }; if ('key' in x) { console.log('has'); }


请注意,它适用于狭义的“对象”,因此声明为 {} 或使用构造函数创建,它不接受数组或原语。并不是说 OP 需要它,而是其他一些答案提供了更广泛的技术(使用数组、字符串等)
@РСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ 感谢您指出这一点(接受的答案没有详细说明为什么应该使用 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/…
K
Konrad Rudolph

注意:由于严格模式和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 吗?
布赖恩:我不是专家,但这看起来确实是一个聪明的方法。
如果著名的“其他人”重新定义了 undefined 是什么,我认为最好的做法是重写该代码。
最好有一个可靠的未定义变量,是在一个闭包中工作,并有一个不匹配的函数签名:(function (undefined) { // undefined is actually undefined here })();
@evanrmurphy 不要使用它,它已经过时了(请参阅我回答开头的注释)。
C
Community
if (x.key !== undefined)

Armin Ronacher 似乎已经有 beat me to it,但是:

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 Ronacheras pointed out 更安全但更慢的解决方案是:

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

我认为这还不够好。 x.hasOwnProperty('toString') === true;
不是要求不同意,而是要理解。除了布尔值 true 或 false 之外,x.hasOwnProperty 是否会返回任何内容?如果没有,发布的代码应该每次都可以工作。我想也许如果该方法被覆盖,但是除非您知道覆盖方法,否则依赖结果将永远不会可靠。
我认为我们沟通不畅。我的意思是使用你的方法,它会说'toString'是它自己的属性,但它不是。
Object.prototype 已经有一个内置的、正确的 hasOwnProperty。用不正确的实现覆盖它(1. 属性可以有值 undefined,2. 这会给继承的属性带来误报)只是一个非常糟糕的主意。不正确的答案可以而且应该被删除。我不知道您是否可以在 08 年 9 月 when you saw Resig's answer 中执行此操作,因此发表评论建议现在执行此操作。
g
goonerify

考虑 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);

这将返回对象上存在的所有属性的名称数组。

Reflections 提供可用于与 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");
}

如果对象上不存在该属性,它将返回未定义的字符串。否则它将返回适当的属性类型。但是,请注意,这并不总是检查对象是否具有属性的有效方法,因为您可以将属性设置为未定义,在这种情况下,使用 typeof x.key 仍会返回 true(即使钥匙仍在对象中)。

同样,您可以通过直接与 undefined Javascript 属性进行比较来检查属性是否存在

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

这应该可以工作,除非在 x 对象上将 key 专门设置为 undefined


A
Aliaksandr Sushkevich

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


P
Peter Mortensen

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

if ('prop' in obj) { }

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

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

John Resig's answer 非常全面,但我认为不清楚。尤其是何时在 obj 中使用“'prop'”。


请注意,in 运算符具有出色的浏览器支持 IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+ stackoverflow.com/questions/2920765/…
正如另一条关于使用 in 运算符的评论中指出的那样:“它适用于狭义的‘对象’,因此声明为 {} 或使用构造函数创建,它不接受数组或原语。不是 OP 要求它,但其他一些答案提供了更广泛的技术(使用数组、字符串等)”
评论因为我已经被否决了两次没有评论。但我还是喜欢我的回答。也许这样做的人想要一个“全面”的答案来测试所有类型的属性。但我的答案是概念性的,为此,简洁。回复:Adrien Be,不可枚举的属性不适用于一般用户范围,因此从概念上讲“in”很好;)
d
davidhadas

要测试简单对象,请使用:

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])...,因为我发现它更具可读性。


A
Armin Ronacher

是的 :) 我认为你也可以做 Object.prototype.hasOwnProperty.call(x, 'key') 如果 x 有一个名为 hasOwnProperty 的属性也应该工作 :)

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


W
Wilt

您还可以使用 the ES6 Reflect object

x = {'key': 1};
Reflect.has( x, 'key'); // returns true

Reflect.has 的 MDN 文档可以在 here 中找到。

静态 Reflect.has() 方法的工作方式类似于 in 运算符作为函数。


j
jprdl

不要这样做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.
console.log(has.call(object, key));
/* Or */
import has from 'has'; // https://www.npmjs.com/package/has
console.log(has(object, key));

我同意这种方法,它应该是公认的答案,因为它是在保持性能的同时最安全的方法! eslint.org/docs/rules/no-prototype-builtins 表示“例如,网络服务器解析来自客户端的 JSON 输入并直接在结果对象上调用 hasOwnProperty 是不安全的,因为恶意客户端可能会发送类似 {"hasOwnProperty": 1} 的 JSON 值并导致服务器崩溃。”
S
Sebastian Simon
if(x.hasOwnProperty("key")){
  // …
}

因为

if(x.key){
  // …
}

如果 x.key 为假(例如 x.key === ""),则失败。


P
Peter Mortensen

好的,除非您不想要继承的属性,否则我似乎有正确的答案:

if (x.hasOwnProperty('key'))

以下是包含继承属性的其他一些选项:

if (x.key) // Quick and dirty, but it does the same thing as below.

if (x.key !== undefined)

警告 x.hasOwnProperty('key') 可以是真的,而 x.key !== undefined 不是真的。
对于 var x = { key: false };x.key 方法不正确。
if (x.key) is not correct as if x = {key:0} 则不会通过检查。
P
Peter Mortensen

另一种相对简单的方法是使用 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

尽管我们所处的世界拥有强大的浏览器支持。因为这个问题太老了,我想我会添加这个:从 JavaScript v1.8.5 开始可以安全使用。


对,但是如果你想知道 info 是否有一个名为 someother 的属性呢?这就是 OP 正在寻找的东西。
然后你会做Object.keys(info).indexOf('someotherthing') !== -1
什么是“JS v1.8.5”? “JavaScript v1.8.5”*?它似乎与任何 ECMAScript 版本都不匹配(版本 8 于 2017 年发布)。 jQuery 1.8 于 2012 年发布。
好的,JavaScript 1.8.5 于 2011 年与 Firefox 4 (2011-03-22) 一起发布。 ECMAScript 5 的第一个版本(链接到)来自 2009 年。
B
Blessing

JavaScript 现在正在发展和成长,因为它现在有很好的甚至有效的方法来检查它。

以下是检查对象是否具有特定属性的一些简单方法:

使用 hasOwnProperty()

const hero = {
  name: 'Batman'
};

hero.hasOwnProperty('name');     // => true
hero.hasOwnProperty('realName'); // => false

在中使用关键字/运算符

const hero = {
  name: 'Batman'
};

'name' in hero;     // => true
'realName' in hero; // => false

与未定义的关键字比较

const hero = {
  name: 'Batman'
};

hero.name;     // => 'Batman'
hero.realName; // => undefined

// So consider this
hero.realName == undefined // => true (which means property does not exists in object)
hero.name == undefined // => false (which means that property exists in object)

有关详细信息,请查看 here


P
Peter Mortensen

hasOwnProperty “可用于确定一个对象是否具有作为该对象的直接属性的指定属性;与 in 运算符不同,此方法不会向下检查对象的原型链。”

因此,很可能,对于您的问题,您不想使用 hasOwnProperty,它确定属性是否直接附加到对象本身。

如果您想确定该属性是否存在于原型链中,您可能希望像这样使用它:

if (prop in object) { // Do something }

我得到“不能使用 'in' 运算符在 myObject 中搜索 'prop'”
P
Peter Mortensen

您可以使用以下方法 -

var obj = {a:1}
console.log('a' in obj)               // 1
console.log(obj.hasOwnProperty('a'))  // 2
console.log(Boolean(obj.a))         // 3

以下方法之间的区别如下 -

在第一种和第三种方法中,我们不仅在对象中搜索,而且也在其原型链中进行搜索。如果对象没有该属性,但该属性存在于它的原型链中,它将给出 true。

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);


Boolean({b:''}.b) -> false
@KamilKiełczewski 是的,它应该给出 false,在这种情况下任何虚假值都将返回 false
K
Kamil Kiełczewski

表现

今天 2020.12.17,我在 Chrome v87、Safari v13.1.2 和 Firefox v83 上对 MacOs HighSierra 10.13.6 进行测试,以选择解决方案。

结果

我只比较解决方案 AF,因为它们为详细信息部分的片段中使用的所有大小写提供了有效结果。适用于所有浏览器

基于(A)中的解决方案是快速或最快的

解决方案(E)对于大对象的 chrome 是最快的,如果 key 不存在,对于小数组的 firefox 是最快的

对于小型阵列,解决方案 (F) 最快(~ > 10 倍于其他解决方案)

解决方案(D,E)非常快

基于 losash 的解决方案 (B) 最慢

https://i.stack.imgur.com/dmfF0.png

细节

我执行 4 个测试用例:

当对象有 10 个字段并且搜索到的键存在时 - 你可以在这里运行它

当对象有 10 个字段并且搜索到的键不存在时 - 您可以在此处运行它

当对象有 10000 个字段并且存在搜索到的键时 - 您可以在此处运行它

当对象有 10000 个字段并且存在搜索到的键时 - 您可以在此处运行它

下面的代码段显示了解决方案之间的差异 A B C D E F G H I J K

// 所以 https://stackoverflow.com/q/135448/860099 // src: https://stackoverflow.com/a/14664748/860099 function A(x) { return 'key' in x } // src: https://stackoverflow.com/a/11315692/860099 function B(x) { return _.has(x, 'key') } // src: https://stackoverflow.com/a/40266120/860099 function C (x) { return Reflect.has( x, 'key') } // src: https://stackoverflow.com/q/135448/860099 function D(x) { return x.hasOwnProperty('key') } / /src: https://stackoverflow.com/a/11315692/860099 function E(x) { return Object.prototype.hasOwnProperty.call(x, 'key') } // src: https://stackoverflow.com/ a/136411/860099 函数 F(x) { 函数 hasOwnProperty(obj, prop) { var proto = obj.__proto__ || obj.constructor.prototype; return (prop in obj) && (!(prop in proto) || proto[prop] !== obj[prop]); } return hasOwnProperty(x,'key') } // src: https://stackoverflow.com/a/135568/860099 function G(x) { return typeof(x.key) !== 'undefined' } // src: https://stackoverflow.com/a/22740939/860099 function H(x) { return x.key !== undefined } // src: https://stackoverflow.com/a/38332171/860099 function I( x) { return !!x.key } // src: https://stackoverflow.com/a/41184688/860099 function J(x) { return !!x['key'] } // src: https:// /stackoverflow.com/a/54196605/860099 function K(x) { return Boolean(x.key) } // -------------------- // TEST / / -------------------- 让 x1 = {'key': 1};让 x2 = {'key': "1"};让 x3 = {'key': true};让 x4 = {'key': []};让 x5 = {'key': {}};让 x6 = {'key': ()=>{}};让 x7 = {'key': ''};让 x8 = {'key': 0};让 x9 = {'key': false};让 x10= {'key': undefined};让 x11= {'nokey': 1};让 b= x=> x ? 1:0; console.log('1 2 3 4 5 6 7 8 9 10 11'); [A,B,C,D,E,F,G,H,I,J,K].map(f=> { console.log(`${f.name} ${b(f(x1)) } ${b(f(x2))} ${b(f(x3))} ${b(f(x4))} ${b(f(x5))} ${b(f(x6)) } ${b(f(x7))} ${b(f(x8))} ${b(f(x9))} ${b(f(x10))} ${b(f(x11)) } ` )}) console.log('\nLegend: Columns (cases)'); console.log('1.key = 1 '); console.log('2.key = "1" '); console.log('3.key = true '); console.log('4.key = [] '); console.log('5.key = {} '); console.log('6.key = ()=>{} '); console.log('7.key = "" '); console.log('8.key = 0'); console.log('9.key = false '); console.log('10.key = undefined '); console.log('11. no-key ');