如何检查对象是否在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
}

这是最好的方法吗?


我真的被给出的答案弄糊涂了——大多数答案都是完全错误的。当然,您可以拥有具有未定义、空或假值的对象属性。因此,简单地将财产检查减少到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解决方案,但有一个警告:它无法区分原型和实例上具有相同属性的情况-它只是假设它来自原型。根据你的情况,你可以把它改为更宽松或更严格,但至少这会更有帮助。


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


注:由于严格模式和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 …
})();


怎么样?

1
2
3
4
5
var x = {'key': 1};

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


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';
};


可以使用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,否则这应该是有效的。


让我们在这里解决一些困惑。首先,假设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"时。


是的,我认为你也可以做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])...,因为我发现它更易于阅读。

玩得高兴。


您还可以使用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)


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

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

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

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

我希望这有帮助。


另一个相对简单的方法是使用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开始使用是安全的


不要这样做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


对象上存在方法"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;

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


您可以使用以下方法-

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];


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

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