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


167

假设我宣布

var ad = {}; 

如何检查该对象是否包含用户定义的属性?

Answers:


86

您可以如下遍历对象的属性:

for(var prop in ad) {
    if (ad.hasOwnProperty(prop)) {
        // handle prop as required
    }
}

使用该hasOwnProperty()方法确定对象是否具有指定的属性作为直接属性,而不是从对象的原型链继承,这一点很重要。

编辑

从注释中: 您可以将该代码放入函数中,并在到达注释部分后立即将其返回false。

性能测试

测试任何属性时测试Object.Keys与For..In


2
丹尼尔,您好,实际上我正在寻找一种设备来检查对象是否包含用户定义的属性。不检查是否存在特定属性。
Ricky

7
@Ricky:您可以将该代码放入函数中,并使其在到达注释的部分时立即返回false。
丹尼尔·瓦萨洛

8
我想用这几天Object.keys将是最简单:var a = [1,2,3];a.something=4;console.log(Object.keys(a))因为它已经ECMA 5的一部分,你可以放心地匀它:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
HMR

2
请注意,在ES5的“这些天”中,本机对象可以具有不可枚举的自身属性,例如Object.defineProperty(obj, 'foo', {enumerable:false, value:'foo'})
RobG 2014年

2
此解决方案是一种检查是否存在键的方法,但是下面使用Object.keys(x).length来提供真实,高效和最正确的答案。您不需要自己做功能,已经存在!
dudewad

193

您可以使用内置Object.keys方法来获取对象上的键列表并测试其长度。

var x = {};
// some code where value of x changes and than you want to check whether it is null or some object with values

if(Object.keys(x).length > 0){
 // Your code here if x has some properties  
}

13
是正确的答案。上面接受的答案是一种解决方法,并且比仅检查键的数量更昂贵;这更有意义
dudewad

6
Object.keys(“ mystring”); 也会产生密钥,我认为这是不可取的。我认为此答案不完整。
Mike de Klerk

2
@MikedeKlerk请仔细阅读,它不是Object.keys(“ mystring”); 它是Object.keys(objectVariableName),它将返回对象中所有键的数组。例如:{'x':'abc','y':'def'}这将是['x','y']
Dhaval Chaudhary

3
@DhavalChaudhary感谢您对我的评论的回复。当我尝试此代码时var str = "MyString"; Object.keys(str);,控制台为每个字符输出0到7之间的8个键。还是我还是不明白答案。
Mike de Klerk

6
@MikedeKlerk,但这仅是对象的解决方案,而不是字符串,请参考问题。
Dhaval Chaudhary

111

做一个简单的函数呢?

function isEmptyObject(obj) {
  for(var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
      return false;
    }
  }
  return true;
}

isEmptyObject({}); // true
isEmptyObject({foo:'bar'});  // false

hasOwnProperty方法调用直接上Object.prototype只加一点更安全,试想使用正常以下obj.hasOwnProperty(...)电话:

isEmptyObject({hasOwnProperty:'boom'});  // false

注意:( 将来) 上述方法依赖于该for...in语句,并且该语句仅在可枚举的属性上进行迭代,在当前使用最广泛的ECMAScript Standard(第3版)中,程序员没有任何方法来创建不可枚举的属性。

但是,现在ECMAScript 5th Edition已经改变了这一点,并且我们能够创建不可枚举,不可写或不可删除的属性,因此上述方法可能会失败,例如:

var obj = {};
Object.defineProperty(obj, 'test', { value: 'testVal', 
  enumerable: false,
  writable: true,
  configurable: true
});
isEmptyObject(obj); // true, wrong!!
obj.hasOwnProperty('test'); // true, the property exist!!

针对此问题的ECMAScript 5解决方案是:

function isEmptyObject(obj) {
  return Object.getOwnPropertyNames(obj).length === 0;
}

Object.getOwnPropertyNames方法返回一个Array含有的名称所有自己的属性的对象的,枚举与否,现在正在实施的浏览器厂商这种方法,它已经在Chrome 5 Beta版和最新的WebKit的每晚构建。

Object.defineProperty 在这些浏览器和最新的Firefox 3.7 Alpha版本上也可用。


1
与obj.hasOwnProperty(prop)相比,Object.prototype.hasOwnProperty.call(obj,prop)有什么优势?
Casey Chu 2010年

3
@Casey,已编辑,如果对象覆盖hasOwnProperty属性,则该函数可能会崩溃...我知道我有点偏执...但是有时您不知道您的代码将在哪种环境中使用,但是你知道你想使用什么方法...
CMS 2010年

2
+1以回答此问题...以及将来的其他问题!:)
丹尼尔·瓦萨洛

1
请注意,IE中还有一个错误,即如果您拥有的属性名称与中的不可枚举属性相匹配Object.prototype,则不会被枚举for...in。所以isEmptyObject({toString:1})会失败。这是你不能不幸的原因之一相当使用Object作为一个通用的映射。
bobince 2010年

1
@ MichaelMartin-Smucker- 仅返回可枚举的自身属性,因此此处不适用。
RobG 2014年

58

使用jQuery,您可以使用:

$.isEmptyObject(obj); // Returns: Boolean

从jQuery 1.4开始,此方法同时检查对象本身的属性和从原型继承的属性(因为它不使用hasOwnProperty)。

使用现代浏览器(IE9 +,FF4 +,Chrome5 +,Opera12 +,Safari5 +)中的ECMAScript 5th Edition,您可以使用内置的Object.keys方法:

var obj = { blah: 1 };
var isEmpty = !Object.keys(obj).length;

或普通的旧JavaScript:

var isEmpty = function(obj) {
               for(var p in obj){
                  return false;
               }
               return true;
            };



11

如果您愿意使用lodash,则可以使用该some方法。

_.some(obj) // returns true or false

看到这个小jsbin 示例


var x = [1,2] // true
djv

@damionjn我将您的代码添加到示例中。我看到您的观点,即数组返回了错误的答案,但是OP最初将变量声明为对象,因此我相信假设这一点是可以的。上面有一个答案使用下划线isEmpty方法(lodash具有相同的方法)。这个答案有完全相同的问题。如果给isEmpty一个非空数组,也会得到错误的结果。
SFS

足够公平,但是我们应该提供涵盖所有基础的答案,以确保最佳实践。没错,我的回答是正确的,没有任何批评。仅对于经过的任何人,这不是专用于对象的方法。_.some([1, 2]) // true 请务必先检查:stackoverflow.com/a/13356338/1922747
djv

5
for (var hasProperties in ad) break;
if (hasProperties)
    ... // ad has properties

如果您必须安全并检查对象原型(这些原型是由某些库添加的,并且默认情况下不存在):

var hasProperties = false;
for (var x in ad) {
    if (ad.hasOwnProperty(x)) {
        hasProperties = true;
        break;
    }
}
if (hasProperties)
    ... // ad has properties

1
在您的解决方案中,不会过滤掉不需要的原型属性,这意味着当使用Prototype.js之类的库或没有经验的用户向对象添加其他原型属性时,它可能会出现异常。在此页面上查看Daniels解决方案。
Joscha

您不必使用库或没有经验就可以扩展对象的原型。一些经验丰富的程序员一直在这样做。
Alsciende 2010年

2
for(var memberName in ad)
{
  //Member Name: memberName
  //Member Value: ad[memberName]
}

成员表示成员属性,成员变量,无论您想调用什么> _>

上面的代码将返回所有信息,包括toString ...如果仅想查看对象的原型是否已扩展:

var dummyObj = {};  
for(var memberName in ad)
{
  if(typeof(dummyObj[memberName]) == typeof(ad[memberName])) continue; //note A
  //Member Name: memberName
  //Member Value: ad[memberName]

}

注意A:我们检查虚拟对象的成员是否与测试对象的成员具有相同的类型。如果是扩展,则dummyobject的成员类型应为“未定义”


嗨,我能知道一个对象是否包含属性吗?谢谢
Ricky

在您的解决方案中,不会过滤掉不需要的原型属性,这意味着当使用Prototype.js之类的库或没有经验的用户向对象添加其他原型属性时,它可能会出现异常。
Joscha

在此页面上查看Daniels解决方案-它不易出错!
Joscha

2
您的第一个代码块根本不会覆盖它。如果我向未定义的“ ad”对象添加变量,则第二个代码块的行为异常。确实,请查看Daniels的答案,它是唯一正确且快速的答案,因为它使用了称为“ hasOwnProperty”的本机实现。
Joscha

@Ricky:如果要检查对象是否包含属性,可以在我的答案中简单使用示例:stackoverflow.com/questions/2673121/…。如果代码到达注释,则您的对象将没有任何直接属性。如果没有,那就可以了。
丹尼尔·瓦萨洛

2
var hasAnyProps = false; for (var key in obj) { hasAnyProps = true; break; }
// as of this line hasAnyProps will show Boolean whether or not any iterable props exist

操作简单,工作在每一个浏览器,即使它在技术上的对象上的所有键它的循环循环通过他们... ...无论有0和循环不运行或有一些它的第一爆发后一个(因为我们要检查的是是否有任何...为什么要继续?)


1

答案很晚,但这就是您可以使用原型处理它的方式。

Array.prototype.Any = function(func) {
    return this.some(func || function(x) { return x });
}

Object.prototype.IsAny = function() {
    return Object.keys(this).Any();
}

0

当确定对象是用户定义的对象时,确定UDO是否为空的最简单方法是以下代码:

isEmpty=
/*b.b Troy III p.a.e*/
function(x,p){for(p in x)return!1;return!0};

即使此方法(从本质上来说)是一种演绎方法,但它是最快,最快的方法。

a={};
isEmpty(a) >> true

a.b=1
isEmpty(a) >> false 

ps :!请勿在浏览器定义的对象上使用它。


...返回0; 返回1};会一样吗?
commonpike 2012年

1
@pike no,return!1; return!0等于return false;返回true
Christophe

0

答案很晚,但是有些框架将对象作为可枚举对象来处理。因此,bob.js可以这样做:

var objToTest = {};
var propertyCount = bob.collections.extend(objToTest).count();

0

您可以使用以下内容:

双砰!属性查询

var a = !![]; // true
var a = !!null; // false

hasOwnProperty 这是我以前使用的东西:

var myObject = {
  name: 'John',
  address: null
};
if (myObject.hasOwnProperty('address')) { // true
  // do something if it exists.
}

但是,JavaScript决定不保护该方法的名称,因此可能会对其进行篡改。

var myObject = {
  hasOwnProperty: 'I will populate it myself!'
};

myObject中的prop

var myObject = {
  name: 'John',
  address: null,
  developer: false
};
'developer' in myObject; // true, remember it's looking for exists, not value.

类型

if (typeof myObject.name !== 'undefined') {
  // do something
}

但是,它不会检查null。

我认为这是最好的方法。

在运算符中

var myObject = {
  name: 'John',
  address: null
};

if('name' in myObject) {
  console.log("Name exists in myObject");
}else{
  console.log("Name does not exist in myObject");
}

结果:

名称存在于myObject中

这是一个有关in运算符的详细链接:确定对象属性是否存在


0

ES6功能

/**
 * Returns true if an object is empty.
 * @param  {*} obj the object to test
 * @return {boolean} returns true if object is empty, otherwise returns false
 */
const pureObjectIsEmpty = obj => obj && obj.constructor === Object && Object.keys(obj).length === 0

例子:


let obj = "this is an object with String constructor"
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = {}
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = []
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = [{prop:"value"}]
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = {prop:"value"}
console.log(pureObjectIsEmpty(obj)) // empty? false

-1

这个怎么样?

var obj = {},
var isEmpty = !obj;
var hasContent = !!obj

这个答案没有回答问题。OP正在询问对象是否包含用户定义的属性-您的答案将检查对象本身是否将转换为布尔假值。
茉莉花

...然后我也意识到詹姆斯已经在他的回答中包括了这个选项。对不起大家。
彼得·托斯
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.