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

考虑:

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

这是最好的方法吗?


当前回答

您需要使用方法object.hasOwnProperty(属性)。如果对象具有该属性,则返回true,如果对象没有,则返回false。

其他回答

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

if (obj[x] !== undefined)

如果您不知道它是什么对象类型,请使用:

if (obj.hasOwnProperty(x))

所有其他选项都较慢。。。

细节

对Node.js下100000000个周期的性能评估,其他人在这里建议了五个选项:

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])。。。因为我觉得它更可读。

以下是针对特定情况的另一个选项。:)

如果要测试对象上的成员,并想知道它是否已设置为以下以外的值:

''假的无效的未定义0...

那么您可以使用:

var foo = {};
foo.bar = "Yes, this is a proper value!";
if (!!foo.bar) {
    // member is set, do something
}

表演

今天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只显示性能测试中使用的函数,而不执行测试本身!

下面是铬的示例结果

一些更简单和简短的选项取决于具体的使用情况:

要检查属性是否存在,无论值如何,请使用in运算符(b中的“a”)要检查变量的属性值,请使用括号符号(obj[v])要将属性值检查为true,请使用optional链接(?)要检查属性值布尔值,请使用double not/bang bang/(!!)要设置空/未定义检查的默认值,请使用空合并运算符(??)要设置假值检查的默认值,请使用短路逻辑OR运算符(||)

运行代码段以查看结果:

让obj1={prop:undefined};console.log(1,obj1中的“prop”);console.log(1,obj1?.prop);let obj2=未定义;//console.log(2,obj2中的“prop”);将引发,因为obj2未定义console.log(2,“prop”in(obj2??{}))console.log(2,obj2?.prop);让obj3={prop:false};console.log(3,obj3中的“prop”);console.log(3,!!obj3?.prop);让obj4={prop:null};let look=“prop”console.log(4,obj4中的“prop”);console.log(4,obj4?.[look]);让obj5={prop:true};console.log(5,obj5中的“prop”);console.log(5,obj5?.prop==true);让obj6={otherProp:true};look=“其他道具”console.log(6,obj6中的“prop”);console.log(6,obj6.look)//应该使用括号符号让obj7={prop:“”};console.log(7,obj7中的“prop”);console.log(7,obj7?.prop||“空”);

我很少看到hasOwn被正确使用的情况,特别是考虑到它的继承问题

不要执行此对象。hasOwnProperty(key))。这真的很糟糕,因为这些方法可能会被相关对象上的财产隐藏起来-请考虑{hasOwn Property:false}-或者,对象可能是空对象(object.create(null))。

最好的方法是执行Object.pr原型.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));