如何检查对象在JavaScript中是否具有特定属性?
考虑:
x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
//Do this
}
这是最好的方法吗?
如何检查对象在JavaScript中是否具有特定属性?
考虑:
x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
//Do this
}
这是最好的方法吗?
是的,它是:)我想你也可以做Object.protype.hasOwnProperty.call(x,'key'),如果x有一个名为hasOwnProperty:)的属性,这也应该有效
但这是对自身财产的测试。如果你想检查它是否有一个属性也可能是固有的,你可以使用typeof x.foo!='未定义”。
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 Rudolph)和阿明·罗纳彻(Armin Ronacher)指出,一个更安全但更慢的解决方案是:
Object.prototype.hasOwnProperty = function(property) {
return typeof this[property] !== 'undefined';
};
好吧,看来我的答案是正确的,除非你不想继承财产:
if (x.hasOwnProperty('key'))
以下是包含继承财产的其他选项:
if (x.key) // Quick and dirty, but it does the same thing as below.
if (x.key !== undefined)
if(x.hasOwnProperty("key")){
// …
}
因为
if(x.key){
// …
}
如果x.key错误(例如,x.key==“”),则失败。
注意:由于严格的模式和OwnProperty,以下内容现在基本上已过时。正确的解决方案是使用strict模式,并使用obj.hasOwnProperty检查是否存在属性。这个答案早于这两种方法,至少在广泛实施时(是的,它已经过时了)。将以下内容作为历史笔记。
请记住,如果不使用严格模式,undefined(不幸的是)不是JavaScript中的保留词。因此,某人(显然是其他人)可能会有重新定义它的宏伟想法,破坏您的代码。
因此,更稳健的方法如下:
if (typeof(x.attribute) !== 'undefined')
另一方面,这种方法更冗长,也更慢-/
一种常见的替代方法是确保undefined实际上是undefineed,例如,将代码放入一个函数中,该函数接受一个未传递值的附加参数,称为undefinede。为了确保它没有传递值,您可以立即调用它,例如:
(function (undefined) {
… your code …
if (x.attribute !== undefined)
… mode code …
})();
2022年更新
Object.hasOwn()
建议使用Object.hasOwn()而不是Object.hasOwnerProperty(),因为它适用于使用Object.create(null)创建的对象以及已重写继承的hasOwnProperty()方法的对象。虽然可以通过对外部对象调用Object.pr原型.hasOwnProperty()来解决这些问题,但Object.hasOwn()更直观。
实例
const object1 = {
prop: 'exists'
};
console.log(Object.hasOwn(object1, 'prop'));
// expected output: true
原答覆
我真的被给出的答案弄糊涂了——大多数答案都是完全错误的。当然,您可以拥有具有未定义、null或false值的对象财产。因此,简单地将属性检查减少为this〔property〕的类型,或者更糟糕的是,x.key将给您带来完全误导的结果。
这取决于你要找什么。如果你想知道一个对象是否在物理上包含一个属性(并且它不是来自原型链上的某个地方),那么object.hasOwnProperty就是最好的方法。所有现代浏览器都支持它。(Safari 2.0.1和更早版本中缺少它,但这些版本的浏览器很少再使用了。)
如果您要查找的是一个对象上是否有可迭代的属性(当您迭代对象的财产时,它就会出现),那么在对象中执行:prop将获得您想要的效果。
由于使用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()的一个有效的跨浏览器解决方案,但有一个警告:它无法区分原型和实例上相同属性的情况-它只是假设它来自原型。根据你的情况,你可以把它改得更宽或更严,但至少这应该更有帮助。
让我们在这里消除一些困惑。首先,让我们通过假设hasOwnProperty已经存在来简化;目前使用的绝大多数浏览器都是如此。
如果传递给它的属性名已添加到对象中,hasOwnProperty返回true。它完全独立于分配给它的实际值,而实际值可能完全未定义。
因此:
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将为false,也将为false!==未定义。然而,对于。。中仍将在枚举中列出它。
最重要的是,没有跨浏览器的方法(因为Internet Explorer不公开__prototype__)来确定特定标识符是否未附加到对象或其原型链中的任何内容。
使用Undercore.js或(甚至更好)Lodash:
_.has(x, 'key');
它调用Object.prototype.hasOwnProperty,但(a)比type短,(b)使用“hasOwnProperty的安全引用”(即,即使hasOwnProperty被覆盖,它也能工作)。
特别是,Lodash将_定义为:
function has(object, key) {
return object ? hasOwnProperty.call(object, key) : false;
}
// hasOwnProperty = Object.prototype.hasOwnProperty
您可以使用此选项(但请阅读以下警告):
变量x={“密钥”:1};如果(x中的“键”){console.log('has');}
但要注意:即使x是一个空对象,x中的“constructor”也会返回true。最好使用Object.hasOwn(x,'key')。
如果您正在搜索属性,请选择“否”。您需要:
if ('prop' in obj) { }
通常,您不应该关心属性是否来自原型或对象。
然而,因为您在示例代码中使用了“key”,所以看起来您将对象视为哈希,在这种情况下,您的答案是有意义的。所有散列键都是对象中的财产,您可以避免原型提供额外的财产。
约翰·雷格的回答很全面,但我认为不清楚。特别是当在obj中使用“rop”时。
考虑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,否则这应该有效
另一种相对简单的方法是使用Object.keys。这将返回一个数组,这意味着您将获得数组的所有特性。
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开始,这是安全的。
hasOwnProperty“可用于确定对象是否具有指定的属性作为该对象的直接属性;与in运算符不同,此方法不检查对象的原型链。”
因此,最有可能的是,根据您的问题,您不想使用hasOwnProperty,它确定属性是否直接附加到对象本身,。
如果要确定该属性是否存在于原型链中,可以使用如下方式:
if (prop in object) { // Do something }
以下是针对特定情况的另一个选项。:)
如果要测试对象上的成员,并想知道它是否已设置为以下以外的值:
''假的无效的未定义0...
那么您可以使用:
var foo = {};
foo.bar = "Yes, this is a proper value!";
if (!!foo.bar) {
// member is set, do something
}
也可以使用ES6 Reflect对象:
x = {'key': 1};
Reflect.has( x, 'key'); // returns true
Reflect.has的MDN文档可在此处找到。
静态Reflect.has()方法的工作方式类似于函数中的in运算符。
对于测试简单对象,请使用:
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])。。。因为我觉得它更可读。
带反射的ECMAScript 6解决方案。创建如下包装:
/**
Gets an argument from array or object.
The possible outcome:
- If the key exists the value is returned.
- If no key exists the default value is returned.
- If no default value is specified an empty string is returned.
@param obj The object or array to be searched.
@param key The name of the property or key.
@param defVal Optional default version of the command-line parameter [default ""]
@return The default value in case of an error else the found parameter.
*/
function getSafeReflectArg( obj, key, defVal) {
"use strict";
var retVal = (typeof defVal === 'undefined' ? "" : defVal);
if ( Reflect.has( obj, key) ) {
return Reflect.get( obj, key);
}
return retVal;
} // getSafeReflectArg
对象上存在一个方法“hasOwnProperty”,但不建议直接调用此方法,因为有时可能是对象为空或对象上存在某些属性,例如:{hasOwnProperty:false}
因此,更好的方法是:
//好的var obj={“bar”:“here bar desc”}console.log(Object.pr原型.hasOwnProperty.call(obj,“bar”));//最佳const has=Object.prototype.hasOwnProperty;//在模块范围内缓存查找一次。console.log(has.call(obj,“bar”));
不要执行此对象。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));
当你能做到以下几点时,不要过于复杂:
var isProperty = (objectname.keyname || "") ? true : false;
对于大多数情况来说,这是简单明了的。。。
您可以使用以下方法-
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');
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)
有关详细信息,请查看此处。
表演
今天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只显示性能测试中使用的函数,而不执行测试本身!
下面是铬的示例结果
迭代对象自身财产的更好方法:
如果要在不使用hasOwnProperty()检查的情况下迭代对象的财产,用于(let key of Object.keys(stud)){}方法:
for(let key of Object.keys(stud)){
console.log(key); // will only log object's Own properties
}
完整示例并与hasOwnProperty()中的for进行比较
function Student() {
this.name = "nitin";
}
Student.prototype = {
grade: 'A'
}
let stud = new Student();
// for-in approach
for(let key in stud){
if(stud.hasOwnProperty(key)){
console.log(key); // only outputs "name"
}
}
//Object.keys() approach
for(let key of Object.keys(stud)){
console.log(key);
}
显示如何使用此答案
const object= {key1: 'data', key2: 'data2'};
Object.keys(object).includes('key1') //returns true
我们也可以使用indexOf,我更喜欢includes
hasOwnProperty()方法返回一个布尔值,指示对象是否将指定的属性作为自己的属性(而不是继承它)。
const object1 = {};
object1.property1 = 42;
console.log(object1.hasOwnProperty('property1'));
// expected output: true
console.log(object1.hasOwnProperty('toString'));
// expected output: false
console.log(object1.hasOwnProperty('hasOwnProperty'));
// expected output: false
了解更多信息
给定myObject对象和“myKey”作为密钥名称:
Object.keys(myObject).includes('myKey')
or
myObject.hasOwnProperty('myKey')
or
typeof myObject.myKey !== 'undefined'
最后一个被广泛使用,但(正如其他答案和评论中所指出的)它也可以匹配从Object原型派生的键。
一些更简单和简短的选项取决于具体的使用情况:
要检查属性是否存在,无论值如何,请使用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被正确使用的情况,特别是考虑到它的继承问题
现在使用ECMAScript22,我们可以使用hasOwn而不是hasOwnProperty(因为这个特性有缺陷)
Object.hasOwn(obj, propKey)