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

考虑:

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

这是最好的方法吗?


当前回答

表演

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

后果

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

基于(A)的解决方案是快速或最快的解决方案(E)对于大型对象的chrome最快,对于小型数组的firefox最快,如果键不存在对于小型阵列,解决方案(F)最快(比其他解决方案快10倍以上)解决方案(D,E)非常快基于洛沙的溶液(B)是最慢的

细节

我执行4个测试用例:

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

下面的代码片段显示了解决方案之间的差异A.BCDEFGH我JK

//所以https://stackoverflow.com/q/135448/860099//第三节:https://stackoverflow.com/a/14664748/860099函数A(x){返回x中的“key”}//第三节:https://stackoverflow.com/a/11315692/860099函数B(x){return _.has(x,'key')}//第三节:https://stackoverflow.com/a/40266120/860099函数C(x){return Reflect.has(x,'key')}//第三节:https://stackoverflow.com/q/135448/860099函数D(x){return x.hasOwnProperty('key')}//第三节:https://stackoverflow.com/a/11315692/860099函数E(x){return Object.pr原型.hasOwnProperty.call(x,'key')}//第三节:https://stackoverflow.com/a/136411/860099函数F(x){函数hasOwnProperty(obj,prop){var proto=obj.__proto__||obj.constructor.prototype;return(obj中的prop)&&(!(proto中的prop)||proto[prop]!==obj[prop]);}return hasOwnProperty(x,'key')}//第三节:https://stackoverflow.com/a/135568/860099函数G(x){返回类型(x.key)!=='未定义'}//第三节:https://stackoverflow.com/a/22740939/860099函数H(x){返回x.key!==未定义}//第三节:https://stackoverflow.com/a/38332171/860099函数I(x){回来x键}//第三节:https://stackoverflow.com/a/41184688/860099函数J(x){回来x[“键”]}//第三节:https://stackoverflow.com/a/54196605/860099函数K(x){返回布尔值(x.key)}// --------------------//测试// --------------------设x1={‘key‘:1};设x2={'key':“1”};让x3={'key':true};让x4={'key':[]};让x5={‘key‘:{}};让x6={'key':()=>{}};让x7={'key':“”};让x8={'key':0};让x9={'key':false};let x10={'key':未定义};设x11={“否”:1};设b=x=>x?1:0;控制台日志(“1 2 3 4 5 6 7 8 9 10 11”);[A,B,C,D,E,F,G,H,I,J,K]映射(F=>{控制台日志(`${f.name}${b(f(x1))}$(f(x2))}}${b(f(x3))}{$(b(f)x4)}${(f(x5))}${f(f(x6)))}${b(f(x7))〕}$}b((f(x8))`)})console.log('\nLegend:列(案例)');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=未定义');console.log('11.no key');<script src=“https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js“integrity=”sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==“crossrorigin=”匿名“></script>此shippet只显示性能测试中使用的函数,而不执行测试本身!

下面是铬的示例结果

其他回答

现在使用ECMAScript22,我们可以使用hasOwn而不是hasOwnProperty(因为这个特性有缺陷)

Object.hasOwn(obj, propKey)

考虑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循环中。此外,如果可枚举属性隐藏了原型的不可枚举属性,它将不会在InternetExplorer8和更早版本中显示。

如果您想要所有实例财产的列表,无论是否可枚举,您可以使用

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属性进行比较来检查属性是否存在

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

除非在x对象上特别将key设置为undefined,否则这应该有效

注意:由于严格的模式和OwnProperty,以下内容现在基本上已过时。正确的解决方案是使用strict模式,并使用obj.hasOwnProperty检查是否存在属性。这个答案早于这两种方法,至少在广泛实施时(是的,它已经过时了)。将以下内容作为历史笔记。


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

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

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

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

一种常见的替代方法是确保undefined实际上是undefineed,例如,将代码放入一个函数中,该函数接受一个未传递值的附加参数,称为undefinede。为了确保它没有传递值,您可以立即调用它,例如:

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

表演

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

后果

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

基于(A)的解决方案是快速或最快的解决方案(E)对于大型对象的chrome最快,对于小型数组的firefox最快,如果键不存在对于小型阵列,解决方案(F)最快(比其他解决方案快10倍以上)解决方案(D,E)非常快基于洛沙的溶液(B)是最慢的

细节

我执行4个测试用例:

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

下面的代码片段显示了解决方案之间的差异A.BCDEFGH我JK

//所以https://stackoverflow.com/q/135448/860099//第三节:https://stackoverflow.com/a/14664748/860099函数A(x){返回x中的“key”}//第三节:https://stackoverflow.com/a/11315692/860099函数B(x){return _.has(x,'key')}//第三节:https://stackoverflow.com/a/40266120/860099函数C(x){return Reflect.has(x,'key')}//第三节:https://stackoverflow.com/q/135448/860099函数D(x){return x.hasOwnProperty('key')}//第三节:https://stackoverflow.com/a/11315692/860099函数E(x){return Object.pr原型.hasOwnProperty.call(x,'key')}//第三节:https://stackoverflow.com/a/136411/860099函数F(x){函数hasOwnProperty(obj,prop){var proto=obj.__proto__||obj.constructor.prototype;return(obj中的prop)&&(!(proto中的prop)||proto[prop]!==obj[prop]);}return hasOwnProperty(x,'key')}//第三节:https://stackoverflow.com/a/135568/860099函数G(x){返回类型(x.key)!=='未定义'}//第三节:https://stackoverflow.com/a/22740939/860099函数H(x){返回x.key!==未定义}//第三节:https://stackoverflow.com/a/38332171/860099函数I(x){回来x键}//第三节:https://stackoverflow.com/a/41184688/860099函数J(x){回来x[“键”]}//第三节:https://stackoverflow.com/a/54196605/860099函数K(x){返回布尔值(x.key)}// --------------------//测试// --------------------设x1={‘key‘:1};设x2={'key':“1”};让x3={'key':true};让x4={'key':[]};让x5={‘key‘:{}};让x6={'key':()=>{}};让x7={'key':“”};让x8={'key':0};让x9={'key':false};let x10={'key':未定义};设x11={“否”:1};设b=x=>x?1:0;控制台日志(“1 2 3 4 5 6 7 8 9 10 11”);[A,B,C,D,E,F,G,H,I,J,K]映射(F=>{控制台日志(`${f.name}${b(f(x1))}$(f(x2))}}${b(f(x3))}{$(b(f)x4)}${(f(x5))}${f(f(x6)))}${b(f(x7))〕}$}b((f(x8))`)})console.log('\nLegend:列(案例)');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=未定义');console.log('11.no key');<script src=“https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js“integrity=”sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==“crossrorigin=”匿名“></script>此shippet只显示性能测试中使用的函数,而不执行测试本身!

下面是铬的示例结果

您可以使用以下方法-

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

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

在第一和第三种方法中,我们不仅搜索对象,还搜索其原型链。如果对象没有该属性,但该属性存在于其原型链中,则该对象将为true。

变量obj={a: 2,__原型__:{b:2}}console.log(obj中的'b')console.log(布尔(obj.b))

第二种方法只检查其自身的财产。示例-

变量obj={a: 2,__原型__:{b:2}}console.log(obj.hasOwnProperty('b'))

第一种方法和第三种方法的区别在于,如果有一个属性的值未定义,则第三种方式将为false,而第一种方法将为true。

变量obj={b:未定义}console.log(布尔(obj.b))console.log(obj中的'b');