Объект пуст?

Каков самый быстрый способ проверить, является ли объект пустым или нет?

Есть ли более быстрый и лучший способ:

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

    return i;
}

Ответы

Ответ 1

Я предполагаю, что пустым вы имеете в виду, что "не имеет собственных свойств".

// 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, вы можете использовать Object.getOwnPropertyNames вместо hasOwnProperty:

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

Это гарантирует, что даже если объект имеет только неперечислимые свойства isEmpty, он все равно даст вам правильные результаты.

Ответ 2

Для ECMAScript5 (пока не поддерживается во всех браузерах), вы можете использовать:

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

Ответ 3

EDIT: обратите внимание, что вместо этого вы, вероятно, должны использовать решение ES5, поскольку поддержка ES5 широко распространена в наши дни. Тем не менее, он все еще работает для jQuery.


Простой и кросс-браузерный способ заключается в использовании jQuery.isEmptyObject:

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

Подробнее: http://api.jquery.com/jQuery.isEmptyObject/

Однако вам нужен jquery.

Ответ 4

Подчеркивание и lodash каждый имеют удобную функцию isEmpty(), если вы не возражаете добавить дополнительную библиотеку.

_.isEmpty({});

Ответ 5

Позволяет положить этого ребенка в постель; тестируется в Node, Chrome, Firefox и IE 9, становится очевидным, что для большинства случаев использования:

  • (для... 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;
}

Результаты в Node:

  • первый результат: 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

Тестирование объекта с помощью двух клавиш 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. - в противном случае используйте более общую (для... в...) реализацию.

Обратите внимание, что Firefox, похоже, имеет более быструю поддержку Object.keys(obj).length и Object.getOwnPropertyNames(obj).length, что делает его лучшим выбором для любого непустого объекта, но все же, когда дело доходит до пустых объектов, (для... in...) просто в 10 раз быстрее.

Мои 2 цента - это то, что Object.keys(obj).length - это плохая идея, поскольку он создает объект ключей, чтобы подсчитать, сколько ключей внутри, чем уничтожает его! Чтобы создать этот объект, ему нужно перекрыть ключи... поэтому зачем использовать его, а не параметр (для... в...):)

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

Ответ 7

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

Ответ 8

Удивлен, увидев так много слабых ответов на такой основной вопрос JS... Верхний ответ тоже не подходит по этим причинам:

  • он генерирует глобальную переменную
  • возвращает true в undefined
  • использует for...in, который сам по себе очень медленный
  • функция внутри for...in бесполезна - return false без hasOwnProperty магия будет работать нормально

На самом деле существует более простое решение:

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

Ответ 9

https://lodash.com/docs#isEmpty поставляется очень удобно:

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

Ответ 10

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/

Ответ 11

Насколько это плохо?

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

    return true; // empty
}

Ответ 12

Вы можете использовать JSON.stringify(obj), а затем сравнить его с пустым объектом. Вот так:

JSON.stringify(your_object)=="{}"

Ответ 13

Нет необходимости в библиотеке.

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

Ответ 14

Вот простая функция, которая проверяет, является ли объект пустым (полезно для проверки нарушения ограничений) из кода todomvc src.

var _isEmptyObject = function (obj) {
    for (var property in obj)
        return false;
    return true;
};

И вот пример из angular:

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

И один из Ionic:

function isObjectEmpty(obj) {
  if (obj) {
    for (var prop in obj) {
      return false;
    }
  }
  return true;
}

Ответ 15

Это может быть немного взломано. Вы можете попробовать это.

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

Не уверен, есть ли недостаток этого метода.

Ответ 16

быстрый onliner для "словарных" объектов:

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

Ответ 17

Вы можете написать резервную копию, если 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;
}

Ответ 18

Представьте, что у вас есть следующие объекты:

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

Не забывайте, что мы не можем использовать знак === для проверки равенства объектов, поскольку они наследуют, поэтому, если вы используете ECMA 5 и верхнюю версию javascript, ответ прост, вы можете использовать следующую функцию:

function isEmpty(obj) {
   //check if it 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

Ответ 19

Я немного поиграл и получил это:

jQuery.isBlank = function (obj) {
    if (!obj || jQuery.trim(obj) === "") return true;
    if (obj.length && obj.length > 0) return false;

    for (var prop in obj) return false;
    return true;
};

console.log(
    $.isBlank(0), // true
    $.isBlank(""), // true
    $.isBlank(null), // true
    $.isBlank(false), // true
    $.isBlank(undefined), // true

    $.isBlank([]), // true
    $.isBlank([null]), // true
    $.isBlank([undefined]), // true

    $.isBlank({}), // true
    $.isBlank({foo: 0}), // false
    $.isBlank({foo: null}), // false
    $.isBlank({foo: false}), // false
    $.isBlank({foo: undefined}), // false

    $.isBlank("Hello"), // false
    $.isBlank([1,2,3]), // false
    $.isBlank({foo: 1}), // false
    $.isBlank({foo: 3, bar: [1,2,3]}), // false

    "incorrect:",
    $.isBlank(1), // true
    $.isBlank(true), // true

    $.isBlank([0]), // false
    $.isBlank([false]), // false
    $.isBlank("0"), // false
    $.isBlank(["0"]), // false
    $.isBlank({foo: "0"}) // false
);

Получилось вдохновение отсюда: https://gist.github.com/laktek/758269#comment-784188

Ответ 20

Может быть, вы можете использовать это решение:

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

Ответ 21

здесь хороший способ сделать это

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

Ответ 22

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
}

Ответ 23

Я изменил код Шона Виейры в соответствии с моими потребностями. 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;

Ответ 24

объект является ассоциативным массивом, дополненным прототипом.

Метод 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
}

Ответ 25

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

Ответ 26

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

Ответ 27

здесь мое решение

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

Стулья