对象是空的吗?

cla*_*rkk 482 javascript

检查对象是否为空的最快方法是什么?

有没有比这更快更好的方法:

function count_obj(obj){
    var i = 0;
    for(var key in obj){
        ++i;
    }

    return i;
}
Run Code Online (Sandbox Code Playgroud)

Jak*_*kob 586

对于ECMAScript5(尽管在所有浏览器中都不支持),您可以使用:

Object.keys(obj).length === 0
Run Code Online (Sandbox Code Playgroud)

  • 更合适的ES5解决方案是`Object.getOwnPropertyNames(obj).length == 0`,因为`Object.keys`只获取*enumerable*属性.在ES5中我们有定义属性属性的能力,我们可以有一个具有非可枚举属性的对象,而`Object.keys`只返回一个空数组...`Object.getOwnPropertyNames`返回一个包含*all*自己的数组对象的属性,即使它们不可枚举. (115认同)
  • 令人难以置信的是,Object.isEmpty()还不是javascript的一部分 (41认同)
  • 这个答案现在[适用于所有现代浏览器](http://kangax.github.io/compat-table/es5/); 绝对是最好的,除非你需要支持IE8-. (11认同)
  • @CMS`getOwnPropertyNames`是[推荐Crockford反对](http://www.youtube.com/watch?v=UTEqr0IlFKY#t=30m43s).根据他的说法,这种方法是专门针对Caja(以及其他安全框架,我猜)的语言引入的.因此,在某些环境中,此方法可能无法使用,也可能无法使用. (9认同)
  • 这是ECMAScript5兼容性表:http://kangax.github.io/es5-compat-table/ (2认同)
  • 从语义上讲,我认为具有**可枚举属性为零的对象**应该被视为“空”(因为无数的已声明属性可能意味着“私有”),所以Object.keys.length可能是正确的方法走。 (2认同)

Sea*_*ira 440

我假设由你的意思是"没有自己的属性".

// Speed up calls to hasOwnProperty
var hasOwnProperty = Object.prototype.hasOwnProperty;

function isEmpty(obj) {

    // null and undefined are "empty"
    if (obj == null) return true;

    // Assume if it has a length property with a non-zero value
    // that that property is correct.
    if (obj.length > 0)    return false;
    if (obj.length === 0)  return true;

    // If it isn't an object at this point
    // it is empty, but it can't be anything *but* empty
    // Is it empty?  Depends on your application.
    if (typeof obj !== "object") return true;

    // Otherwise, does it have any properties of its own?
    // Note that this doesn't handle
    // toString and valueOf enumeration bugs in IE < 9
    for (var key in obj) {
        if (hasOwnProperty.call(obj, key)) return false;
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)

例子:

isEmpty(""), // true
isEmpty(33), // true (arguably could be a TypeError)
isEmpty([]), // true
isEmpty({}), // true
isEmpty({length: 0, custom_property: []}), // true

isEmpty("Hello"), // false
isEmpty([1,2,3]), // false
isEmpty({test: 1}), // false
isEmpty({length: 3, custom_property: [1,2,3]}) // false
Run Code Online (Sandbox Code Playgroud)

如果您只需要处理ECMAScript5浏览器,则可以使用Object.getOwnPropertyNames而不是hasOwnProperty循环:

if (Object.getOwnPropertyNames(obj).length > 0) return false;
Run Code Online (Sandbox Code Playgroud)

这将确保即使对象仅具有非可枚举属性,isEmpty仍将为您提供正确的结果.

  • @SeanVieira is_empty({length:0,custom_property:[]})返回false.我不确定你打算如何使用代码,但如果你添加:if(obj.length === 0)返回true,我会期待它; 在if之后(obj.length && obj.length> 0)返回false; 这是正确的 (4认同)
  • @pgreen2 - 好收获!我已更新示例以包含对 0 的显式检查 - 感谢您帮助改进答案! (2认同)
  • @frequent - `var hasOwnProp`可能也会起作用:-)我们希望避免尽可能多的查找(如果在一个性能类型很重要的地方调用[如果它真的很重要只有分析会告诉你每个平台上最快的方式]). (2认同)

joh*_*odo 219

编辑:请注意,您应该使用ES5解决方案而不是这个,因为ES5支持目前很普遍.它仍适用于jQuery.


简单和跨浏览器的方式是使用jQuery.isEmptyObject:

if ($.isEmptyObject(obj))
{
    // do something
}
Run Code Online (Sandbox Code Playgroud)

更多:http://api.jquery.com/jQuery.isEmptyObject/

你需要jquery.

  • 我很高兴jQuery选项是"典型的,值得额外的赏金",超过[原生ES5解决方案](http://stackoverflow.com/a/4994265/425313).我想这个答案在某些情况下仍然有用. (49认同)
  • @Pier我觉得你在这里故意是钝的.跨浏览器并不表示它包含在浏览器本身中,只是它在主要接受的浏览器中普遍适用. (4认同)
  • 并非所有浏览器都支持ES5解决方案(至少AFAIK),因此如果您已经在使用jQuery(许多站点都是),这个解决方案是有意义的.此外,jQuery比Jakob的解决方案更有效(但在大多数情况下并不重要),因为它在计算长度之前不会遍历整个对象 - 它会在找到密钥时返回[false](https ://github.com/jquery/jquery/blob/master/src/core.js#L241). (2认同)

Bra*_*och 95

如果你不介意添加额外的库,下划线lodash每个都有一个方便的isEmpty()功能.

_.isEmpty({});
Run Code Online (Sandbox Code Playgroud)

  • 或者已经包含下划线的人;) (19认同)
  • 迟到评论:至于2016年你可以使用lodash _isEmpty_(你不需要导入所有的lodash,你现在可以从中导入一个方法,它在npm中被分成多个微包). (6认同)

dav*_*das 62

让这个宝宝上床睡觉; 在Node,Chrome,Firefox和IE 9下测试,很明显,对于大多数用例:

  • (for ... in ...)是最快的选择!
  • Object.keys(obj).length对于空对象来说慢10倍
  • JSON.stringify(obj).length总是最慢的(不奇怪)
  • Object.getOwnPropertyNames(obj).length比Object.keys(obj)更长.在某些系统上,.length可能要长得多.

明智的底线表现,使用:

function isEmpty(obj) { 
   for (var x in obj) { return false; }
   return true;
}
Run Code Online (Sandbox Code Playgroud)

要么

function isEmpty(obj) {
   for (var x in obj) { if (obj.hasOwnProperty(x))  return false; }
   return true;
}
Run Code Online (Sandbox Code Playgroud)

节点下的结果:

  • 第一个结果: return (Object.keys(obj).length === 0)
  • 第二个结果: for (var x in obj) { return false; }...
  • 第三个结果: for (var x in obj) { if (obj.hasOwnProperty(x)) return false; }...
  • 第四个结果: return ('{}' === JSON.stringify(obj))

使用0键测试对象0.00018 0.000015 0.000015 0.000324

使用1个键测试对象0.000346 0.000458 0.000577 0.000657

使用2个键0.000375 0.00046 0.000565 0.000773测试对象

使用3个键测试对象0.000406 0.000476 0.000577 0.000904

使用4个键测试对象0.000435 0.000487 0.000589 0.001031

使用5个键测试对象0.000465 0.000501 0.000604 0.001148

使用6个键测试对象0.000492 0.000511 0.000618 0.001269

用7个键测试对象0.000528 0.000527 0.000637 0.00138

用8个键测试对象0.000565 0.000538 0.000647 0.00159

使用100个键测试对象0.003718 0.00243 0.002535 0.01381

使用1000个键测试对象0.0337 0.0193 0.0194 0.1337

请注意,如果您的典型用例使用少量键测试非空对象,并且很少使用10个或更多键测试空对象或对象,请考虑Object.keys(obj).length选项. - 否则请使用更通用的(for ... in ...)实现.

请注意,Firefox似乎更快地支持Object.keys(obj).length和Object.getOwnPropertyNames(obj).length,使其成为任何非空对象的更好选择,但是当涉及空对象时,( for ... in ...)只是快了10倍.

我的2美分是Object.keys(obj).length是一个糟糕的主意,因为它创建一个键对象来计算内部有多少键,而不是销毁它!为了创建该对象,他需要循环键...所以为什么要使用它而不是(for ... in ...)选项:)

var a = {};

function timeit(func,count) {
   if (!count) count = 100000;
   var start = Date.now();
   for (i=0;i<count;i++) func();
   var end = Date.now();
   var duration = end - start;
   console.log(duration/count)
}

function isEmpty1() {
    return (Object.keys(a).length === 0)
}
function isEmpty2() {
    for (x in a) { return false; }
    return true;
}
function isEmpty3() {
    for (x in a) { if (a.hasOwnProperty(x))  return false; }
    return true;
}
function isEmpty4() {
    return ('{}' === JSON.stringify(a))
}


for (var j=0;j<10;j++) {
   a = {}
   for (var i=0;i<j;i++) a[i] = i;
   console.log('Testing for Object with '+Object.keys(a).length+' keys')
   timeit(isEmpty1);
   timeit(isEmpty2);
   timeit(isEmpty3);
   timeit(isEmpty4);
}

a = {}
for (var i=0;i<100;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1);
timeit(isEmpty2);
timeit(isEmpty3);
timeit(isEmpty4, 10000);

a = {}
for (var i=0;i<1000;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1,10000);
timeit(isEmpty2,10000);
timeit(isEmpty3,10000);
timeit(isEmpty4,10000);
Run Code Online (Sandbox Code Playgroud)


小智 30

优雅的方式 - 使用键

var myEmptyObj = {};
var myFullObj = {"key":"value"};
console.log(Object.keys(myEmptyObj).length); //0
console.log(Object.keys(myFullObj).length); //1
Run Code Online (Sandbox Code Playgroud)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

  • 为什么没有人评论这个解决方案?在我看来很好. (2认同)

Šim*_*das 22

function isEmpty( o ) {
    for ( var p in o ) { 
        if ( o.hasOwnProperty( p ) ) { return false; }
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)


Too*_*kit 17

var x= {}
var y= {x:'hi'}
console.log(Object.keys(x).length===0)
console.log(Object.keys(y).length===0)

true
false
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/j7ona6hz/1/


meg*_*otz 15

很惊讶在这样一个基本的JS问题上看到这么多弱的答案......由于这些原因,最佳答案也不好:

  1. 它生成一个全局变量
  2. 返回trueundefined
  3. 使用for...in本身非常慢
  4. 里面的函数for...in是没用的 - false没有hasOwnProperty魔法的返回会很好

事实上,有一个更简单的解决方案:

function isEmpty(value){
    return Boolean(value && typeof value == 'object') && !Object.keys(value).length;
});
Run Code Online (Sandbox Code Playgroud)

  • 我认为在undefined上返回false是可以的,因为undefined不是一个对象. (7认同)

Paw*_*lik 11

https://lodash.com/docs#isEmpty非常方便:

_.isEmpty({})   // true
_.isEmpty()     // true
_.isEmpty(null) // true
_.isEmpty("")   // true
Run Code Online (Sandbox Code Playgroud)


Kar*_*yal 7

这有多糟糕?

function(obj){
    for(var key in obj){
        return false; // not empty
    }

    return true; // empty
}
Run Code Online (Sandbox Code Playgroud)