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

How do I check if an object has a property in JavaScript?

如何检查一个对象在javascript中是否有属性?

考虑:

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

这是最好的方法吗?

  • 我用每个人的答案编写了一个JSperf测试,看看哪个速度最快:jspef.com/dictionary-contains-key
  • (对象中的"propertyname")?属性存在":"属性不存在
  • @Stifle感谢JSPERF测试。对于我来说,inhasOwnProperty的速度比其他的慢(98%)。我对hasOwnProperty变慢并不感到惊讶,但我对in感到惊讶。


我真的被给出的答案弄糊涂了——大多数答案都是完全错误的。当然,您可以拥有具有未定义、空或假值的对象属性。因此,简单地将财产检查减少到typeof this[property],或者更糟的是,x.key会给您带来完全误导性的结果。

这取决于你在找什么。如果您想知道一个对象在物理上是否包含一个属性(并且它不是来自原型链上的某个位置),那么object.hasOwnProperty就是解决问题的方法。所有的现代浏览器都支持它。(它在旧版本的Safari(2.0.1和更旧版本)中丢失了,但这些版本的浏览器已很少使用。)

如果您要查找的是一个对象上是否有一个不可重写的属性(当您迭代该对象的属性时,它会出现),那么执行:prop in object将为您提供所需的效果。

由于使用hasOwnProperty可能是您想要的,并且考虑到您可能需要一个回退方法,我向您介绍以下解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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如果您正在构建一个简单的Slider插件,并且想要检查选项项的存在性,那么这可能比实际需要的要多。你可以做一些像var w = opts.w || 100;这样的事情。但是如果你在图书馆之类的地方,你可能需要在某些地方走得更远一点。
  • @Kralco626:是的,现在我觉得使用hasownproperty()是相当安全的——但是对于真正安全的跨浏览器解决方案,使用john的。
  • 暂时把__proto__改为空怎么样?简单的例子:function hasOwnProperty(obj, prop) { var temp = obj.__proto__; obj.__proto__ = null; var ret = prop in obj; obj.__proto__ = temp; return ret; }(加obj.constructor.prototype的情况)。
  • @kasztan __proto__是非标准的,在一些老版本的浏览器中不起作用。即使最近增加了Object.getPrototypeOf,该标准也表示您仍然无法更改现有对象的原型。
  • JohnResig的答案在IE8中似乎不起作用,在这个实况演示jsbin.com/tovaburefeva/1/edit中看到它失败了吗?JS,输出。我认为这是因为hasOwnProperty()"is not supported on host objects for Internet Explorer 8 and below"参见msdn.microsoft.com/en-us/library/ie/328kyd6z(v=v s.94).aspx和stackoverflow.com/questions/8157700/…
  • for(prop in object)循环只迭代可枚举的属性。然而,prop in object检查object是否在原型链的某个地方具有prop的属性,这与它是否可枚举无关。
  • 作为在if's中声明的函数的旁注,这在我所知道的所有现代浏览器中都有效,但phantomjs不支持它。
  • 因为ECMA脚本版本6嵌入了反射函数,这是首选的方式。它有一个"has()"和一个"get()",这使得创建一个包装器来获取安全参数非常容易。并非所有的浏览器都支持这种功能(不是在IE和Opera中),但这种功能很快就会改变。使用ECMA"使用版本6"确保脚本版本正确。


使用Underscore.js或(甚至更好)lodash时:

1
_.has(x, 'key');

它调用Object.prototype.hasOwnProperty,但(a)比类型短,(b)使用"对hasOwnProperty的安全引用"(即,即使hasOwnProperty被覆盖,它也能工作)。

特别是,lodash将_.has定义为:

1
2
3
4
   function has(object, key) {
      return object ? hasOwnProperty.call(object, key) : false;
   }
   // hasOwnProperty = Object.prototype.hasOwnProperty

  • 我想这是因为"添加这个库"很少是一个流行的解决方案,即使问题是关于复杂的DOM操作,答案是"使用jquery"。
  • 我明白你的意思,@sudhown,谢谢。顺便说一句,如果一个人不愿意包括整个lodash库,他可以编译子组件或npm install lodash.has,它只使用has函数公开一个NPM模块,当被缩小时,它可以编译到175字节。看看lodash.has/index.js也很有洞察力,看看一个非常受欢迎和信任的图书馆是如何运作的。
  • lodash的版本是这样工作的:.has(undefined, 'someKey') => falseunderscore返回undefined
  • 谢谢@bradparks——我实际上没有看过underscore版本的文档,所以我相信这对于阅读本文的人来说可能是一个有用的观点。
  • 谢谢@brian-m-hunt,我已经包括了lodash,在我本应该成为RTFM之前就开始四处搜索了。
  • 我不认为使用库是一个可以接受的答案,因为这个问题问的是"在javascript中"而不是"使用javascript库"。
  • 对于每一个抱怨将lodash添加为"又一个"依赖项的人来说:对于这类事情,它是一个相当常见的(如果不是最常见的)库。享受重新设计车轮的乐趣。
  • 即使你想重新发明轮子,检查现有的轮子也不是一个坏主意。
  • 另外,运营商可能还不知道这一点。所以说'在javascript'或'与jquery'并不意味着他们不开放的新库,他们可能不知道存在,只是试图使用基本的javascript或jquery,因为他们认为这是他们所拥有的一切在他们的处置。但是,所选择的使用"hasownproperty"的回答是最简单的方法。
  • 为了上帝的爱,使用罗达什或其他任何图书馆,直到JS整理出它的美丽,小脑袋。至少,如果你走这条路,你就要为浏览器的兼容性卸载大量的循环跳跃。问题:已解决。继续前进。


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

记住,如果您不使用严格模式,那么undefined在javascript中不是保留字(不幸的是)。因此,有人(显然是其他人)可能会有重新定义它、破坏代码的宏伟构想。

因此,一种更为稳健的方法是:

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

另一方面,这种方法更冗长,速度也更慢。- -

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

1
2
3
4
5
(function (undefined) {
    … your code …
    if (x.attribute !== undefined)
        … mode code …
})();

  • 只是好奇,既然void 0被定义为返回标准undefined,那么可以做x.attribute !== void 0吗?
  • 布莱恩:我不是专家,但这似乎是一个很好的方法。
  • 如果著名的"其他人"重新定义了未定义的内容,我认为最好的做法是重写代码。
  • undefined = (function () {}()); if (a.attribute !== undefined) 'foo';
  • 最好是有一个实的未定义的var,在一个闭包内工作,并且有一个不匹配的函数签名:(function (undefined) { // undefined is actually undefined here })();
  • "未定义"不是只读的吗?因此不再有问题了?
  • 由于ES5严格模式,您不能再重新定义未定义的,但您必须记住打开严格模式。:)此外,此答案不测试对象是否具有某些属性,而是测试属性是否未定义(包括现有和不存在的属性)。
  • @Brianm.Hunt你的建议与x.attribute !== void 0void(0)在我的测试中效果很好。
  • @埃文墨菲不使用这个词,它已经过时了(见我答案开头的注释)。


怎么样?

1
2
3
4
5
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/…


1
if (x.key !== undefined)

Armin Ronacher似乎已经打败了我,但是:

1
2
3
4
5
6
7
8
9
10
11
12
13
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!');
}

康拉德·鲁道夫(KonradRudolph)和阿敏·罗纳赫(Armin Ronacher)指出,一个更安全但速度较慢的解决方案是:

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

  • 我觉得这还不够好。x.hasOwnProperty('toString') === true;
  • 不是要求不同意,而是理解。除了布尔值"真"或"假"之外,x.hasownProperty还会返回其他值吗?如果没有,则每次都应该使用已发布的代码。我想,如果方法被重写,那么依赖于结果将永远不可靠,除非您知道重写方法。
  • 我认为我们沟通有误。我的意思是,使用您的方法,它会说"ToString"是它自己的属性,但它不是。
  • Object.prototype已经有了内置的、正确的hasOwnProperty。用不正确的实现(1)覆盖它。属性的值可以是undefined,2。这会给继承属性带来误报)只是一个可怕的坏主意。不正确的答案可以也应该删除。我不知道你是否能在08年9月看到Resig的回答时做到这一点,所以评论建议现在就做。


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

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

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

1
2
3
4
5
for (prop in x) {
    if (prop =="key") {
        //Do something
    }
}

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

如果需要所有实例属性的列表,无论是否可枚举,都可以使用

1
Object.getOwnPropertyNames(x);

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

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

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

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

更新:通过与未定义的javascript属性比较,可以检查属性是否存在。

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

除非X对象上的key被专门设置为undefined,否则这应该是有效的。

  • 更新部分错误。请看这里:jsfiddle.net/sbgg04yg
  • 更新以显示与javascript未定义属性比较可能失败的方案


让我们在这里解决一些困惑。首先,假设hasOwnProperty已经存在,让我们简化一下;这是当前使用的大多数浏览器的情况。

如果传递给它的属性名已添加到对象中,则hasOwnProperty返回true。它完全独立于分配给它的实际值,可能正好是undefined

因此:

1
2
3
4
5
var o = {}
o.x = undefined

var a = o.hasOwnProperty('x')  // a is true
var b = o.x === undefined // b is also true

然而:

1
2
3
4
var o = {}

var a = o.hasOwnProperty('x')  // a is now false
var b = o.x === undefined // b is still true

问题是,当原型链中的对象具有值为"未定义"的属性时会发生什么?hasOwnProperty对它来说是错误的,!== undefined也是错误的。然而,for..in仍将在列举中列出。

底线是没有跨浏览器的方法(因为Internet Explorer不公开__prototype__)来确定特定标识符没有附加到对象或其原型链中的任何内容。


如果您正在搜索属性,则选择"否"。你想要:

1
if ('prop' in obj) { }

一般来说,您不应该关心属性是否来自原型或对象。

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

约翰·雷西格的回答很全面,但我觉得不清楚。尤其是在obj中使用"prop"时。

  • 请注意,in运营商具有出色的浏览器支持IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+stackoverflow.com/questions/2920765/…
  • 正如另一条关于使用in运算符的注释所指出的那样:"它在狭义上与‘对象’一起工作,因此声明为或使用构造函数创建,它不接受数组或基元。"不是说OP需要它,而是其他一些答案提供了更广泛的技术(使用数组、字符串等)。
  • 评论,因为我两次被否决,没有评论。但我还是喜欢我的回答。也许是谁想要一个"全面"的答案来测试所有类型的属性。但我的回答是概念性的,而且是简明扼要的。回复:adrien be,不可数属性是指不适用于一般用户范围的属性,因此概念上"in"是可以的;)


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

但这是对自身属性的测试。如果你想检查它是否有一个属性,也可能是固有的,你可以使用typeof x.foo != 'undefined'


1
2
3
if (typeof x.key !="undefined") {

}

因为

1
if (x.key)

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


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

如果不知道它使用的对象类型:if (obj.hasOwnProperty(x))

所有其他选项都比较慢。

细节

在Nodejs下对其他人建议的5个选项进行100000000个周期的性能评估:

1
2
3
4
5
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倍。

1
2
3
4
5
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.hasownpropy(x))…"。

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

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

玩得高兴。

  • 在这里比较Reflect.has也很有趣。


您还可以使用es6 Reflect对象:

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

有关Reflect.has的MDN的文档可在此处找到。

The static Reflect.has() method works like the in operator as a function.

  • 创建一个好的包装,比如:


好吧,看起来我的回答是对的,除非你不想继承财产:

1
if (x.hasOwnProperty('key'))

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

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

if (x.key !== undefined)

  • 注意x.hasownProperty("key")可以是真的,而x.key!==未定义不是真的。
  • 对于var x = { key: false };来说,x.key方法是不正确的。
  • 如果(x.key)不正确,就像x=key:0一样,它将不会通过检查。


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

因此,最可能的情况是,对于您的问题,您不想使用hasownpropy,它决定了属性是否直接附加到对象本身。

如果要确定原型链中是否存在该属性,您主要希望在其中使用,例如:

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

我希望这有帮助。

  • 我得到"不能使用"in"运算符在myObject中搜索"prop"的信息"


另一个相对简单的方法是使用Object.keys。这将返回一个array,这意味着您可以获得数组的所有特性。

1
2
3
4
5
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开始使用是安全的

  • 是的,但是如果你想知道信息是否有一个名字是其他东西的财产呢?这就是OP正在寻找的。
  • 那你就做Object.keys(info).indexOf('someotherthing') !== -1


不要这样做object.hasOwnProperty(key)),这是非常糟糕的,因为这些方法可能被所讨论对象的属性(考虑{ hasOwnProperty: false })所隐藏,或者对象可能是空对象(Object.create(null))

最好的方法是执行Object.prototype.hasOwnProperty.call(object, key)或:

1
2
3
4
5
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));

考虑到大量投票被否决的风险,这里是另一个具体案例的选择。:)

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

  • 无效的
  • 未定义
  • 零…

然后您可以使用:

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

带反射的ECMA脚本6解决方案。创建包装方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
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时,这是最好的方法吗?
  • imho它是最短和最简单的答案,但可能不是执行代码中最快的。但速度不再是问题了。


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

所以更好的方法是:

1
2
3
4
5
6
7
// 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"));


当你能做到的时候,为什么过于复杂化?

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

简单明了,适用于大多数情况…

  • 最简单的是var isproperty=!!objectname.keyname;


您可以使用以下方法-

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

以下方法的区别如下-

  • 在第1和第3种方法中,我们不仅在对象中搜索,而且在原型链也是。如果对象没有属性,但是该属性存在于它将给出的原型链中。真的。
  • 1
    2
    3
    4
    5
    6
    7
     var obj = {
          a:2,
          __proto__ :{b:2}
        }

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

  • 第二种方法只检查其自身属性。前-
  • 1
    2
    3
    4
    5
    6
    var obj = {
          a:2,
          __proto__ :{b:2}
        }

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

  • 第一个和第三个的区别是,如果有一个属性的值未定义,那么第三个方法将给出false,而第一个方法将给出true。
  • 1
    2
    3
    4
    5
    var obj = {
          b : undefined
        }
        console.log(Boolean(obj.b))
        console.log('b' in obj);


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


    如果要检查的键存储在变量中,可以这样检查:

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

    • 这在概念上有什么不同,然后只是测试x["key"]?和x.key有什么不同?当然,在访问数组时除外。


    我用过这个。如果你有一个物体在物体里面,这对我有很大帮助

    1
    2
    3
    if(typeof(obj["key"])=="string"){
        alert("property");
    }