对象是空的吗?

时间:2011-02-14 15:53:52

标签: javascript

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

是否有比这更快更好的方法:

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

    return i;
}

24 个答案:

答案 0 :(得分:556)

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

Object.keys(obj).length === 0

答案 1 :(得分:429)

我假设 empty 你的意思是“没有自己的属性”。

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

示例:

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

如果您只需要处理ECMAScript5 browsers,则可以使用Object.getOwnPropertyNames代替hasOwnProperty循环:

if (Object.getOwnPropertyNames(obj).length > 0) return false;

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

答案 2 :(得分:217)

编辑:请注意,您应该使用ES5 solution代替此,因为ES5支持目前为widespread。它仍适用于jQuery。


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

if ($.isEmptyObject(obj))
{
    // do something
}

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

你需要jquery。

答案 3 :(得分:96)

Underscorelodash每个都有一个方便的isEmpty()函数,如果您不介意添加额外的库。

_.isEmpty({});

答案 4 :(得分:57)

让我们把这个孩子放到床上;在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;
}

function isEmpty(obj) {
   for (var x in obj) { if (obj.hasOwnProperty(x))  return false; }
   return true;
}

节点下的结果:

  • 第一个结果: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,使其成为任何非空对象的更好选择,但仍然适用于空对象,(......中...)只是快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);

答案 5 :(得分:29)

优雅的方式 - 使用键

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

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

答案 6 :(得分:22)

function isEmpty( o ) {
    for ( var p in o ) { 
        if ( o.hasOwnProperty( p ) ) { return false; }
    }
    return true;
}

答案 7 :(得分:15)

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

true
false

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

答案 8 :(得分:15)

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

  1. 它会生成一个全局变量
  2. true
  3. 上返回undefined
  4. 使用for...in本身非常慢
  5. for...in内的函数无用 - 返回false没有hasOwnProperty魔法就行了
  6. 事实上,有一个更简单的解决方案:

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

答案 9 :(得分:12)

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

_.isEmpty({})   // true
_.isEmpty()     // true
_.isEmpty(null) // true
_.isEmpty("")   // true

答案 10 :(得分:6)

这有多糟糕?

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

    return true; // empty
}

答案 11 :(得分:4)

不需要图书馆。

function(){ //must be within a function
 var obj = {}; //the object to test

 for(var isNotEmpty in obj) //will loop through once if there is a property of some sort, then
    return alert('not empty')//what ever you are trying to do once

 return alert('empty'); //nope obj was empty do this instead;
}

答案 12 :(得分:3)

可能有点hacky。你可以试试这个。

if (JSON.stringify(data).length === 2) {
   // Do something
}

不确定此方法是否存在缺点

答案 13 :(得分:1)

如果Array.isArray和Object.getOwnPropertyNames不可用,您可以编写回退

XX.isEmpty = function(a){
    if(Array.isArray(a)){
        return (a.length==0);
    }
    if(!a){
        return true;
    }
    if(a instanceof Object){

        if(a instanceof Date){
            return false;
        }

        if(Object.getOwnPropertyNames(a).length == 0){
            return true;
        }
    }
    return false;
}

答案 14 :(得分:1)

快速在线搜索'词典'对象:

function isEmptyDict(d){for (var k in d) return false; return true}

答案 15 :(得分:1)

想象一下,你有以下对象:

var obj1= {};
var obj2= {test: "test"};

不要忘记我们不能使用=== sign来测试对象的相同性,因为它们可以继承,所以如果你使用ECMA 5和javascript的高级版本,答案很简单,你可以使用下面的函数:

function isEmpty(obj) {
   //check if it's an Obj first
   var isObj = obj !== null 
   && typeof obj === 'object' 
   && Object.prototype.toString.call(obj) === '[object Object]';

   if (isObj) {
       for (var o in obj) {
           if (obj.hasOwnProperty(o)) {
               return false;
               break;
           }
       }
       return true;
   } else {
       console.error("isEmpty function only accept an Object");
   }
}

所以结果如下:

isEmpty(obj1); //this returns true
isEmpty(obj2); //this returns false
isEmpty([]); // log in console: isEmpty function only accept an Object

答案 16 :(得分:1)

funtion isEmpty(o,i)
{
    for(i in o)
    {
        return!1
    }
    return!0
}

答案 17 :(得分:0)

可能你可以使用这个决定:

var isEmpty = function(obj) {
  for (var key in obj)
    if(obj.hasOwnProperty(key))
      return false;
  return true;
}

答案 18 :(得分:0)

这是一个很好的方法

function isEmpty(obj) {
  if (Array.isArray(obj)) {
    return obj.length === 0;
  } else if (typeof obj === 'object') {
    for (var i in obj) {
      return false;
    }
    return true;
  } else {
    return !obj;
  }
}

答案 19 :(得分:0)

var hasOwnProperty = Object.prototype.hasOwnProperty;
function isArray(a) {
    return Object.prototype.toString.call(a) === '[object Array]'
}
function isObject(a) {
    return Object.prototype.toString.call(a) === '[object Object]'
}
function isEmpty(a) {
    if (null == a || "" == a)return!0;
    if ("number" == typeof a || "string" == typeof a)return!1;
    var b = !0;
    if (isArray(a)) {
        if (!a.length)return!0;
        for (var c = 0; c < a.length; c++)isEmpty(a[c]) || (b = !1);
        return b
    }
    if (isObject(a)) {
        for (var d in a)hasOwnProperty.call(a, d) && (isEmpty(a[d]) || (b = !1));
        return b
    }
    return!0
}

答案 20 :(得分:0)

我根据自己的需要修改了Sean Vieira的代码。 null和undefined根本不算作对象,数字,布尔值和空字符串返回false。

'use strict';

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

var isObjectEmpty = function(obj) {
    // null and undefined are not empty
    if (obj == null) return false;
    if(obj === false) return false;
    if(obj === true) return false;
    if(obj === "") return false;

    if(typeof obj === "number") {
        return false;
    }   
    
    // 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;

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

exports.isObjectEmpty = isObjectEmpty;

答案 21 :(得分:-1)

if (Object.getOwnPropertyNames(obj1).length > 0)
{
 alert('obj1 is empty!');
}

答案 22 :(得分:-1)

这是我的解决方案

function isEmpty(value) {
    if(Object.prototype.toString.call(value) === '[object Array]') {
        return value.length == 0;
    } else if(value != null && typeof value === 'object') {
        return Object.getOwnPropertyNames(value).length  == 0;
    } else {
        return !(value || (value === 0));
    }
}

CHEARS

答案 23 :(得分:-1)

  

一个对象是一个关联数组,用原型扩充。

     

Object.is()方法确定两个值是否相同。

对象的比较: -

Object.is('LOL', 'LOL');// true
Object.is(console, console);// true
Object.is(null, null);// true
Object.is('ROFL', 'LOL');// false
Object.is([], []);// false
Object.is(0, -0);// false
Object.is(NaN, 0/0);// true

if (!Object.is)
{
   // do something
}