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


1486

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

考虑:

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

那是最好的方法吗?


21
我写了一个jsperf测试,每个人的答案都是最快的:jsperf.com/dictionary-contains-key
styfle

(对象中的“ propertyName”)?“财产在那里”:“财产在那里”
Mohan Ram

1
@styfle感谢您的jsperf测试。inhasOwnProperty出来的方式比别人慢,我(98%速度较慢)。我对hasOwnProperty变慢并不感到惊讶,但我对此感到惊讶in
evanrmurphy

Answers:


1423

我对所给出的答案感到困惑-他们中的大多数都是完全错误的。当然,您可以拥有具有未定义,空值或假值的对象属性。因此,简单地将属性检查减少到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,但有一个警告:不能区分原型和实例上具有相同属性的情况-只是假设它来自原型。您可以根据自己的情况将其更改为宽容或严格,但是至少这应该会有所帮助。


5
@grantwparks如果您正在构建一个简单的滑块插件,并且想要检查选项项的存在,那么可能确实超出了需要。您可以做类似的事情var w = opts.w || 100;。但是,如果您使用某种库,则可能需要在某些地方走得更远。
HalilÖzgür

@ kralco626:是的,如今,我觉得使用hasOwnProperty()很安全-但是要获得真正安全的跨浏览器解决方案,请使用John's。
2012年

什么临时变更__proto__为空?简单IMPL: function hasOwnProperty(obj, prop) { var temp = obj.__proto__; obj.__proto__ = null; var ret = prop in obj; obj.__proto__ = temp; return ret; }(壳,obj.constructor.prototype应补充)。
平均乔

2
@Kasztan __proto__是非标准的,在某些较旧的浏览器中不起作用。即使最近添加了Object.getPrototypeOf该标准,您仍然不能更改现有对象的原型。
马特·布朗

13
一个for(prop in object)循环迭代仅枚举的属性。但是,独立于是否可枚举,prop in object检查object属性是否prop在原型链中某个位置。
Oriol

283

使用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

52
我想这是因为即使问题是关于复杂的DOM操作并且答案是“使用jQuery”,“添加此库”也很少是流行的解决方案。
Winfield Trail 2014年

11
我明白你的意思,@ sudown,谢谢。顺便说一句,如果不喜欢包含整个lodash库,则可以编译子组件,或者npm install lodash.has公开一个npm模块,而该has函数只有在最小化时才编译为175个字节。查看并lodash.has/index.js了解非常受欢迎且值得信赖的库的工作原理也是很有见地的。
Brian M. Hunt 2014年

9
lodash的版本适用本: .has(undefined, 'someKey') => false虽然underscore回报undefined
布拉德公园

13
对于每个渴望添加lodash“又一个”依赖关系的人:对于这种事情,它是一个相当普通的(如果不是最常见的)库。玩转车轮吧。
Priidu Neemre '16

11
即使您想重新发明轮子,检出现有轮子也不是坏主意。
AturSams

147

关于什么?

var x = {'key': 1};

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

13
只是要注意,它在狭义上与“对象”一起使用,因此声明为{}或使用构造函数创建,它不接受数组或基元。并不是说OP要求它,而是一些其他答案提出了更广泛的技术(使用数组,字符串等)
Danubian Sailor 2014年

@РСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ感谢指出了这一点(接受的答案不会进入上为什么要使用明细in操作或不还要注意的是,in运营商具有优秀的浏览器支持IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+ stackoverflow.com/questions/2920765/...
阿德里安铍

2
操作员in还检查原型属性,而hasOwnProperty仅迭代用户定义的属性。参考:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
adi518

2
'key' in x 确实可以处理数组。证明: stackoverflow.com/questions/33592385/...
CosmoMyzrailGorynych

似乎是最好和最短的选项
user365314

132

注意:由于采用严格模式,因此以下内容已过时hasOwnProperty。正确的解决方案是使用严格模式,并使用来检查属性的存在obj.hasOwnProperty。这个答案早于这两件事,至少已经广泛实施了(是的,它已经很老了)。将以下内容作为历史记录。


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

因此,一种更可靠的方法如下:

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

另一方面,这种方法比较冗长,而且速度较慢。:-/

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

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

6
只是好奇,既然void 0定义了返回规范undefined,可以x.attribute !== void 0吗?
Brian M. Hunt,

1
布莱恩:我不是专家,但是那肯定是解决问题的聪明方法。
Christopher Smith,

37
如果著名的“其他人”重新定义了undefined,我认为最好的做法是重写THAT代码。
Oskar Holmkratz 2013年

3
具有可靠的未定义var的最佳方法是在闭包中工作并且具有无与伦比的函数签名:(function (undefined) { // undefined is actually undefined here })();
bgusach 2013年

1
@evanrmurphy不要使用它,它已经严重过时了(请参阅答案开头的注释)。
康拉德·鲁道夫

55
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!');
}

一个更安全,但速度较慢的解决方案,如指出,康拉德·鲁道夫阿明Ronacher将是:

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

2
我认为那还不够好。x.hasOwnProperty('toString') === true;
乔·西蒙斯

不是要提出异议,而是要理解。除了布尔true或false之外,x.hasOwnProperty还可以返回什么吗?如果不是,发布的代码应该每次都起作用。我想也许该方法被覆盖了,但是,除非您知道该覆盖方法,否则依赖结果永远是不可靠的。
enobrev 2013年

1
我认为我们沟通不畅。我的意思是,使用您的方法时,它会说“ toString”是它自己的属性,但不是。
乔·西蒙斯

3
Object.prototype已经具有内置的正确的hasOwnProperty。用不正确的实现覆盖它(1.属性可以具有值undefined2。这将为继承的属性提供误报)只是一个可怕的坏主意。错误答案可以并且应该删除。当您看到Resig的答案时,我不知道您是否可以在08年9月做得到,所以发表评论建议现在就这样做。
TJ Crowder

36

您可以使用in运算符检查属性是否存在于对象上:

x = {'key': 1};
alert("key" in x);

您还可以使用循环遍历对象的所有属性for - in,然后检查特定属性:

for (prop in x) {
    if (prop == "key") {
        //Do something
    }
}

您必须考虑此对象属性是否可枚举,因为不可枚举的属性不会for-in循环显示。另外,如果可枚举属性遮盖了原型的不可枚举属性,则它将不会显示在Internet Explorer 8及更早版本中。

如果您想要所有实例属性的列表(无论是否可枚举),则可以使用

Object.getOwnPropertyNames(x);

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

最后,您可以使用typeof运算符直接检查对象属性的数据类型:

if (typeof x.key == "undefined") {
    alert("undefined");
}

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

更新:您可以通过与未定义的javascript属性进行比较来检查属性是否存在

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

除非将密钥专门设置为undefinedx对象,否则此方法应该起作用


您的更新部分错误。请在这里看看:jsfiddle.net/sbgg04yg
Number945 '17

已更新以显示与JavaScript undefined属性进行比较可能失败的方案
goonerify

31

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


24

如果要搜索属性,则为“ NO”。你要:

if ('prop' in obj) { }

通常,您不必关心该属性是否来自原型或对象。

但是,由于在示例代码中使用了“键”,因此看起来您将对象视为哈希,在这种情况下,您的答案才有意义。所有哈希键都将是对象中的属性,并且可以避免原型带来的额外属性。

John Resig的回答非常全面,但我认为还不清楚。特别是当在obj中使用“ prop”时。


1
请注意,in运营商具有优秀的浏览器支持IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+ stackoverflow.com/questions/2920765/...
阿德里安要

正如在有关使用in运算符的另一条评论中指出的那样:“它在狭义上与'对象'一起工作,因此声明为{}或使用构造函数创建,它不接受数组或基元。不是OP要求它,而是其他一些答案则提出了更为广泛的技术(使用数组,字符串等)”
Adrien Be

1
发表评论的原因,我两次被拒绝发表评论。但是我仍然喜欢我的答案。也许这样做的人想要一个“全面”的答案,以所有方式来测试所有类型的属性。但是我的答案是概念性的,因此简洁。回复:阿德里安·贝(Adrien Be),无数的属性并不适合一般用户使用,因此从概念上讲“ in”就可以了;)
Gerard ONeill

16

要测试简单对象,请使用: if (obj[x] !== undefined)

如果您不知道它是什么对象类型,请使用: if (obj.hasOwnProperty(x))

所有其他选项都较慢。

细节

在Nodejs下,其他人建议的5个选项下的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: 4s 510.427785ms
hasKey2 execution time: 0s 904.374806ms
hasKey3 execution time: 0s 760.336193ms
hasKey4 execution time: 0s 935.19901ms
hasKey5 execution time: 2s 148.189608ms

底线是,如果您的Obj不一定是简单的对象,并且您希望避免检查对象的原型链,并确保x直接由Obj拥有,请使用'if(obj.hasOwnProperty(x))...'。

否则,当使用简单的对象而不必担心对象的原型链时,使用if (typeof(obj[x]) !== 'undefined')...是最安全,最快的方法。

如果您使用一个简单的对象作为哈希表并且从不做任何事情,那么我将使用if (obj[x])...它,因为我发现它更具可读性。

玩得开心。


15

是的,它是:)我想您也可以这样做Object.prototype.hasOwnProperty.call(x, 'key'),如果x有一个叫做hasOwnProperty:) 的属性也应该可以工作

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


14
if (typeof x.key != "undefined") {

}

因为

if (x.key)

如果x.key解析为false(例如),则失败x.key = ""


不会是正确的。尝试以下对象const x = {key: undefined};,该对象在x.hasOwnProperty('key')); // true和时将返回false Reflect.has(x, 'key')); // true。该属性实际上存在,但值是undefined
Wilt


10

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

if (x.hasOwnProperty('key'))

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

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

if (x.key !== undefined)

4
警告x.hasOwnProperty('key')可以为true,而x.key!== undefined则不为true。
AnthonyWJones

4
对于var x = { key: false };x.key方法将是不正确的。
2014年

2
如果(x.key)好像x = {key:0}一样不正确,它将不会通过检查。
someUser

10

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

3
我同意这种方法,它应该是公认的答案,因为这是保持性能的最安全方法!eslint.org/docs/rules/no-prototype-builtins说:“例如,网络服务器解析客户端的JSON输入并直接在生成的对象上调用hasOwnProperty是不安全的,因为恶意客户端可以发送JSON值例如{“ hasOwnProperty”:1}并导致服务器崩溃。
阿曼

7

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

尽管我们处在一个强大的浏览器支持中。因为这个问题太老了,所以我想添加一下:从JS v1.8.5开始可以安全使用


是的,但是如果您想知道info是否具有名称为otherothering的属性,该怎么办?这就是OP正在寻找的东西。
Victorio Berra 2015年

2
然后您会做Object.keys(info).indexOf('someotherthing') !== -1
hippietrail

7

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

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

如果要确定该属性是否存在于主要要使用的原型链中,例如:

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

我希望这有帮助。


我收到“无法使用'in'运算符在myObject中搜索'prop'”
Victorio Berra

3

由于存在大规模投票的风险,因此这是针对特定情况的另一种选择。:)

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

  • ''
  • 空值
  • 未定义
  • 0 ...

那么您可以使用:

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

紧凑且方便
Frederik Witte


2

ECMA Script 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

当您定位> = ES6时,这是最好的方法吗?
hippietrail

1
恕我直言,这是最短,最简单的答案,但可能不是最快的执行代码。但是速度不再是问题。
危害

2

对象上存在方法“ hasOwnProperty”,但不建议直接调用此方法,因为有时对象可能为null或对象上存在某些属性,例如: { hasOwnProperty: false }

更好的方法是:

// good
var obj = {"bar": "here bar desc"}
console.log(Object.prototype.hasOwnProperty.call(obj, "bar"));

// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
console.log(has.call(obj, "bar"));


2

您可以使用以下方法-

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

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

  1. 在第一种和第三种方法中,我们不仅在对象中进行搜索,而且还搜索其原型链。如果对象不具有该属性,但是该属性存在于其原型链中,则它将为真。

 var obj = {
      a:2,
      __proto__ :{b:2}
    }

    console.log('b' in obj)
    console.log(Boolean(obj.b))

  1. 第二种方法将仅检查其自身的属性。前-

var obj = {
      a:2,
      __proto__ :{b:2}
    }

    console.log(obj.hasOwnProperty('b'))

  1. 第一和第三之间的区别是,如果有一个属性的值未定义,则第三种方法将为假,而第一种方法将为真。

var obj = {
      b : undefined
    }
    console.log(Boolean(obj.b))
    console.log('b' in obj);



-1

如果您要检查的密钥存储在变量中,则可以像这样检查它:

x = {'key': 1};
y = 'key';
x[y];

这与仅测试x ['key']的概念有何不同?那和x.key有什么不同?其他访问当然的阵列的情况相比..
杰拉德奥尼尔

-1

为什么要使事情变得过于复杂:

var isProperty =  (objectname.keyname || "") ? true : false;

在大多数情况下简单明了...


最简单的方法是var isProperty = !! objectname.keyname;
约翰

如果对象如下const objectName = { keyname: false };,则应返回true,因为keyname是的属性objectname。但是由于该值为false,因此使用此逻辑将返回false。
Wilt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.