How do I test for an empty JavaScript object?
Asked Answered
C

41

3892

After an AJAX request, sometimes my application may return an empty object, like:

var a = {};

How can I check whether that's the case?

Chateau answered 25/3, 2009 at 1:39 Comment(0)
L
7480

You can use a for…in loop with an Object.hasOwn (ECMA 2022+) test to check whether an object has any own properties:

function isEmpty(obj) {
  for (const prop in obj) {
    if (Object.hasOwn(obj, prop)) {
      return false;
    }
  }

  return true;
}

If you also need to distinguish {}-like empty objects from other objects with no own properties (e.g. Dates), you can do various (and unfortunately need-specific) type checks:

function isEmptyObject(value) {
  if (value == null) {
    // null or undefined
    return false;
  }

  if (typeof value !== 'object') {
    // boolean, number, string, function, etc.
    return false;
  }

  const proto = Object.getPrototypeOf(value);

  // consider `Object.create(null)`, commonly used as a safe map
  // before `Map` support, an empty object as well as `{}`
  if (proto !== null && proto !== Object.prototype) {
    return false;
  }

  return isEmpty(value);
}

Note that comparing against Object.prototype like in this example will fail to recognize cross-realm objects.

Do not use Object.keys(obj).length. It is O(N) complexity because it creates an array containing all the property names only to get the length of that array. Iterating over the object accomplishes the same goal but is O(1).

For compatibility with JavaScript engines that don’t support ES 2022+, const can be replaced with var and Object.hasOwn with Object.prototype.hasOwnProperty.call:

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

  return true
}

Many popular libraries also provide functions to check for empty objects:

jQuery:

jQuery.isEmptyObject({}); // true

lodash:

_.isEmpty({}); // true

Underscore:

_.isEmpty({}); // true

Hoek:

Hoek.deepEqual({}, {}); // true

ExtJS:

Ext.Object.isEmpty({}); // true

AngularJS (version 1):

angular.equals({}, {}); // true

Ramda:

R.isEmpty({}); // true
Liturgist answered 25/3, 2009 at 1:39 Comment(16)
Object.keys(new Date()).length === 0; so this answer can be misleading.Fernanda
This returns true for an object that is not empty, but all its keys are symbols.Glassworker
The ECMA 5+ version will give incorrect results for empty objects created using Object.create(null).Austral
I think javascript should create something to check whether an object is empty or add length property to the object.Upstanding
Is JSON.stringify(obj) === "{}" a potential effective solution?Utilitarian
@Utilitarian Yes, potentially, and it’s already in the answer. It’s not a very good solution, though (slow, no more reliable and sometimes less).Botryoidal
For primitive falsy values like 0 or empty string '' the ES5+ version returns that same primitive and not exactly false. I think the first line can be obj !== undefined instead of obj.Algo
@Utilitarian It is insufficient because this following object would also return "{}": { pirate: undefined }Ceramist
A more readable way to compare prototypes: obj.constructor == Object instead of Object.getPrototypeOf(obj) === Object.prototype.Chamfer
@Chema: Also a wrong way to compare prototypes, e.g. {constructor: "foo"}, Object.assign(Object.create(null), {constructor: Object}), ….Botryoidal
I really wish this answer wasn't selected. Creating a new array, with unknown number of entries, is O(N) complexity, and completely unnecessary. Use the for loop with early exit.Circle
And noting the bad behavior is worse than not knowing; it means you knew, and posted it anyway, and now this answer has 7k+ votes. UG. This is why we can't have nice things. Sorry, cranky today, don't mean to punch down on an answer that is easy and, therefore, tempting.Circle
Sorry for the rant. I've proposed the changes as I think they should be. Reviewers, come at me. 🤣Circle
@colinta: Thanks for doing that! I wasn’t brave enough :DBotryoidal
@Circle I see how creating the new array has O(N) complexity, but how is looping through any better?? That is also O(N), even with an early exit. How do you figure it is O(1)?Fetich
The only case where this would loop through all the properties is when the object's prototype has a bunch of keys, but the object in question is empty. I'm thinking of the more likely scenario, where we have a plain ol JavaScript object and it may or may not be "empty". In that case, it will only enter that loop once. But you're right in that there are cases where this would be O(N) - but the keys().length solution will always create that unnecessary array full of keys that get thrown away.Circle
C
1413

If ECMAScript 5 support is available, you can use Object.keys():

function isEmpty(obj) {
    return Object.keys(obj).length === 0;
}

For ES3 and older, there's no easy way to do this. You'll have to loop over the properties explicitly:

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

    return true;
}
Calc answered 25/3, 2009 at 1:49 Comment(11)
This works fine, or more simply: function isEmpty(object) { for(var i in object) { return true; } return false; }Harlandharle
Shouldnt true and false be reversed in this function?Raybin
@namtax: no - the function is named isEmpty(), so it should return false if it has a propertyCalc
@NicholasKreidberg That code function isEmpty(object) { for(var i in object) { return true; } return false; } got to be corrected after 11 years. Here's the correction: function isEmpty(obj) { return !(() => { for (const i in obj) { return true; } return false; })(); }Debar
Alernatively: function isObjectEmpty(obj) { for (const i in obj) return false; return true; }Debar
Note that the code in isEmpty alone is not enough, though. You also want to test for obj.constructor === Object, in case you're dealing with objects that have a million non-enumerable properties, which Object.keys() explicitly will not includeStage
what for the if(obj.hasOwnProperty(prop)) ?Detoxicate
isEmpty({ hasOwnProperty: "where is your god now?" })Bedspread
@Bedspread is right! This should be updated to Object.hasOwn(obj, prop)Circle
@Harlandharle true and false should be reversed, see the comment from 5th july 2021Voluptuous
we shouldn't waste an incredible amount of cpu resources juste because a syntax looks elegant. if you're object has 1000 keys, Object.keys() will create an array with 1000 element which you absolutely don't need. @Harlandharle answer is a lot better (with reversing true and false).Southeasterly
O
590

For those of you who have the same problem but use jQuery, you can use jQuery.isEmptyObject.

Oversoul answered 19/5, 2010 at 14:7 Comment(3)
This won't work if you (or any plugin) modified Object.prototype.Cocoa
note that this works fine for the question asked, {}, but that jQuery.isEmptyObject([]) === true, presumably because an empty list is iterable.Fenn
Note that jQuery.isEmptyObject returns false when you feed it an empty jQuery object (as noted on its API page). It only works for regular JavaScript objects.Transubstantiate
S
397

Performance

Today 2023.3.20 I perform tests for chosen solutions on MacOs Monterey 12.1 (M1, 16GB) on Chrome v109, Safari v15.2 and Firefox v110.

Conclusions

  • Solutions based on for-in (A, L) are fast or fastest on all browsers
  • Solution based on JSON.stringify (B) is slowest on all browsers

enter image description here

Details

There solutions are presented in the snippet below. If you want to run a performance test on your machine, click

  • HERE for empty object
  • HERE for object witch 10 fields
  • HERE for object with 100 fields

Old version of this answer contains tests from 2020 - HERE.

Links to answers: A, B, C, D, E, F, G, H, I, J, K, L, M, N, O P Q

var log = (s, f) => console.log(`${s} --> {}:${f({})}  {k:2}:${f({ k: 2 })}`);

function A(obj) {
  for (var i in obj) return false;
  return true;
}

function B(obj) {
  return JSON.stringify(obj) === "{}";
}

function C(obj) {
  return Object.keys(obj).length === 0;
}

function D(obj) {
  return Object.entries(obj).length === 0;
}

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

function F(obj) {
  return Object.keys(obj).length === 0 && obj.constructor === Object;
}

function G(obj) {
  return typeof obj === "undefined" || !Object.keys(obj)[0];
}

function H(obj) {
  return Object.entries(obj).length === 0 && obj.constructor === Object;
}

function I(obj) {
  return Object.values(obj).every((val) => typeof val === "undefined");
}

function J(obj) {
  for (const key in obj) {
    if (hasOwnProperty.call(obj, key)) {
      return false;
    }
  }
  return true;
}

function K(obj) {
  var isEmpty = true;
  for (keys in obj) {
     isEmpty = false;
     break;
  }
  return isEmpty;
}

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

function M(obj) {
  if (obj === null || typeof obj !== 'object' ||
    Object.prototype.toString.call(obj) === '[object Array]') {
    return false
  } else {
    for (var prop in obj) {
      if (obj.hasOwnProperty(prop)) {
        return false
      }
    }
    return JSON.stringify(obj) === JSON.stringify({})
  }
}

function N(obj) {
  return (
    Object.getOwnPropertyNames(obj).length === 0 &&
    Object.getOwnPropertySymbols(obj).length === 0 &&
    Object.getPrototypeOf(obj) === Object.prototype
  );
}

function O(obj) {
  return !(Object.getOwnPropertyNames !== undefined
    ? Object.getOwnPropertyNames(obj).length !== 0
    : (function () {
        for (var key in obj) break;
        return key !== null && key !== undefined;
      })());
}

function P(obj) {
  return $.isEmptyObject(obj)
}

function Q(obj) {
  return _.isEmpty(obj);
}

log("A", A);
log("B", B);
log("C", C);
log("D", D);
log("E", E);
log("F", F);
log("G", G);
log("H", H);
log("I", I);
log("J", J);
log("K", K);
log("L", L);
log("M", M);
log("N", N);
log("O", O);
log("P", P);
log("Q", Q);
<script
  src="https://code.jquery.com/jquery-3.6.4.min.js"
  integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8="
  crossorigin="anonymous"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.6/underscore-min.js" integrity="sha512-2V49R8ndaagCOnwmj8QnbT1Gz/rie17UouD9Re5WxbzRVUGoftCu5IuqqtAM9+UC3fwfHCSJR1hkzNQh/2wdtg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

enter image description here

Steeve answered 17/1, 2020 at 12:53 Comment(6)
a lot of this doesn't make sense because you're basing everything on a return of false and or true. Sometimes programming needs an if statement or a ternary operator. just fyiRockling
For completeness, I edited your jsperf to test obj = {a:1,b:2,c:3} and for(var i in obj) is still the fastest jsperf.com/object-empty-ch/2Starbuck
@Christian Matthew Okay, (o => { for(let k in o) return false; return true; })(obj)Paganism
@ChristianMatthew with the exception of B-E, everything else should go into its own function anyway...they're too verbose otherwise.Dairen
I created a fork of the test changing the initial object to contain 10000 elements and the results are really different: jsbench.me/hplcsahs9e/1 . At least in Firefox and Chromium Object.values clearly wins, which confirms my other test result: jsben.ch/a3bT7 . Thank You anyway! I just believe the answer requires editing.Mean
Moronix has better benchmarks than this. Most of those snippets are not remotely equivalent, so it makes little sense to compare them. (K) and (L) are basically the same code, though (with the former missing a return true), yet one is 25% slower than the other… which suggests the differences are so minute anyway that it shouldn’t matter, they are going to be dwarfed by the cost of a function call in which they will be inevitably wrapped, by JIT and garbage collection jitter and other noise.Bedspread
C
236

You can use Underscore.js.

_.isEmpty({}); // true
Coraleecoralie answered 22/3, 2011 at 20:35 Comment(2)
Or you could use lodash is empty (lodash.com/docs#isEmpty), but how is that any different from using a jQuery solution - you still need to install an additional library. I think a vanilla javascript solution is the intent.Summertree
If adding the entire dependency is mortifying to your super-performance dependent application, you can install just _.isEmpty: npm i lodash.isemptyUella
L
135
if(Object.getOwnPropertyNames(obj).length === 0){
  //is empty
}

see http://bencollier.net/2011/04/javascript-is-an-object-empty/

Letrice answered 6/11, 2013 at 13:48 Comment(3)
This includes non-enumerable properties, in case you care.Mast
The Object.getOwnPropertyNames({}).length is 10 times slower than the (for...in...) option - I suggest to avoid it as a way to test if an objetc is empty.Polygamy
Object.getOwnPropertyNames(new Date()).length === 0; so this answer can be misleading.Fernanda
V
105

How about using JSON.stringify? It is almost available in all modern browsers.

function isEmptyObject(obj){
    return JSON.stringify(obj) === '{}';
}
Victualler answered 23/1, 2013 at 20:7 Comment(6)
This is slow and speed matters for this kind of utility. Quick perf test here: jsperf.com/empty-object-testSiamese
This is a very slow option - I suggest to use the (for...in) option insteadPolygamy
And it doesn't work for objects that contain functions.Charpoy
It will also throw an error if there's a circular reference in the object. So it's slow, unreliable and can throw errors and break everything else. No reason to use it ever.Chivy
Please note that JSON.stringify(new Error('gotcha')) === '{}' is trueMaggie
Performance might be important - that's for the OP to determine. They also stated that the object has been parsed from an Ajax service so we know it's not going to be a date, an exception, or have methods. The stringify method is very readable and doesn't depend on external libraries so it has a lot to recommend it in some casesDelisadelisle
S
94

There is a simple way if you are on a newer browser. Object.keys(obj).length === 0

Snowstorm answered 29/4, 2012 at 19:25 Comment(6)
Where does the keys property come from?Mast
It's a standard method in ECMAScript 5.1Snowstorm
How can the above comment have 4 upvotes? Yes, Object.keys is a standard method but objects do not have a keys property. So this code will report any object as empty except it accidentally happens to have a property named key with a value which again as a property named length which is not zero. Horrible!Isometropia
Object.keys(new Date()).length === 0; so this answer can be misleading.Fernanda
@Isometropia Object is the class Object. Object has a static method named 'keys' which accepts an object as an argument. This method returns an array of strings where the strings are property names. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Remscheid
@Fernanda you posted the same in several answers. I can't view it as misleading since the question is about object literal, parsed from JSON response in a Ajax. The only time it will be an issue is if https response body is "null".Pinsky
C
64

Old question, but just had the issue. Including JQuery is not really a good idea if your only purpose is to check if the object is not empty. Instead, just deep into JQuery's code, and you will get the answer:

function isEmptyObject(obj) {
    var name;
    for (name in obj) {
        if (obj.hasOwnProperty(name)) {
            return false;
        }
    }
    return true;
}
Cachucha answered 31/1, 2013 at 10:55 Comment(2)
This is only useful if some other process hasn't added a prototype to your base object. To make this truly workable, you need to test for obj.hasOwnProperty(name)Berkowitz
isEmptyObject({ hasOwnProperty: "where is your god now?" })Bedspread
P
51

Using Object.keys(obj).length (as suggested above for ECMA 5+) is 10 times slower for empty objects! keep with the old school (for...in) option.

Tested under Node, Chrome, Firefox and IE 9, it becomes evident that for most use cases:

  • (for...in...) is the fastest option to use!
  • Object.keys(obj).length is 10 times slower for empty objects
  • JSON.stringify(obj).length is always the slowest (not suprising)
  • Object.getOwnPropertyNames(obj).length takes longer than Object.keys(obj).length can be much longer on some systems.

Bottom line performance wise, use:

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

or

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

See detailed testing results and test code at Is object empty?

Polygamy answered 28/12, 2015 at 10:40 Comment(1)
Object.keys is slow, but less code. On a small page, where this is called... maybe 10 times... Will this still be slower considering the additional parsing time of the additional code?Bioscopy
M
37

My take:

function isEmpty(obj) {
  return Object.keys(obj).length === 0;
}

var a = {
  a: 1,
  b: 2
}
var b = {}

console.log(isEmpty(a)); // false
console.log(isEmpty(b)); // true

Just, I don't think all browsers implement Object.keys() currently.

Member answered 31/10, 2011 at 13:39 Comment(2)
Object.keys(new Date()).length === 0; so this answer can be misleading.Fernanda
Depends if you consider a date being always "full" despite never exposing keys. But I agree that if that's your plan, adding some supplementary instanceof check for Date constructor is a good option.Member
J
33

I am using this.

function isObjectEmpty(object) {
  var isEmpty = true;
  for (keys in object) {
     isEmpty = false;
     break; // exiting since we found that the object is not empty
  }
  return isEmpty;
}

Eg:

var myObject = {}; // Object is empty
var isEmpty  = isObjectEmpty(myObject); // will return true;
 
// populating the object
myObject = {"name":"John Smith","Address":"Kochi, Kerala"}; 
 
// check if the object is empty
isEmpty  = isObjectEmpty(myObject); // will return false;

from here

Update

OR

you can use the jQuery implementation of isEmptyObject

function isEmptyObject(obj) {
  var name;
  for (name in obj) {
    return false;
  }
  return true;
}
Jonasjonathan answered 8/6, 2012 at 8:4 Comment(4)
hi. when you test this function with number or boolean true or false return true and this is not correct result. isObjectEmpty(true). isObjectEmpty(false). isObjectEmpty(1)Resource
We are checking whether the object is empty, not if the data type is an object. In your case to check if its an object we need to something like if(typeof a === "object") {...}Jonasjonathan
on react I get keys is not definedIphigenia
@Iphigenia Try for (const keys in object) {Jonasjonathan
S
30

1. Using Object.keys

Object.keys will return an Array, which contains the property names of the object. If the length of the array is 0, then we know that the object is empty.

function isEmpty(obj) {
    return Object.keys(obj).length === 0 && obj.constructor === Object;
}

We can also check this using Object.values and Object.entries. This is typically the easiest way to determine if an object is empty.

2. Looping over object properties with for…in

The for…in statement will loop through the enumerable property of object.

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

    return true;
}

In the above code, we will loop through object properties and if an object has at least one property, then it will enter the loop and return false. If the object doesn’t have any properties then it will return true.

#3. Using JSON.stringify If we stringify the object and the result is simply an opening and closing bracket, we know the object is empty.

function isEmptyObject(obj){
    return JSON.stringify(obj) === '{}';
}

4. Using jQuery

jQuery.isEmptyObject(obj); 

5. Using Underscore and Lodash

_.isEmpty(obj);

Resource

Sauerbraten answered 19/7, 2020 at 5:53 Comment(1)
What does it mean : && obj.constructor === Object?Gossipmonger
S
27
  1. Just a workaround. Can your server generate some special property in case of no data?

    For example:

    var a = {empty:true};
    

    Then you can easily check it in your AJAX callback code.

  2. Another way to check it:

    if (a.toSource() === "({})")  // then 'a' is empty
    

EDIT: If you use any JSON library (f.e. JSON.js) then you may try JSON.encode() function and test the result against empty value string.

Stowage answered 25/3, 2009 at 11:48 Comment(11)
toSource() is non-standard and doesn't work in IE or Opera (and potentially other browsers I didn't check)Calc
This is standard in ECMA-262. There are non-standard browsers though.Stowage
@Thevs: perhaps you have a different copy of the current version of ECMA-262, but mine does not list a toSource property in section 15.2.4; according to MDC, it was introduced in JS1.3 (i.e. Netscape Navigator 4.06), but it's NOT in ECMA-262, 3rd edition!Calc
@Christoph: How do you think 3 other browsers would implement the same 'non-standard' feature if that wouldn't be a standard? :)Stowage
@Thevs: well, at least 2 important browser vendors didn't implement it, so it's hardly a de-facto-standard, and as it's not in ECMA-262, it's not a real one either...Calc
...and as for how features get implemented across different browsers without being standard: ever heard of innovation and a thing called copying? It's how the standard was developed ion the first place (JavaScript and JScript predate ECMAScript)Calc
BTW, toSource() is implemented in IE internally, but nor exposed to outside. Think why?Stowage
There is no such method as toSource()Sb
Even when it does work, toSource() is a horrible way to do this (as is JSON.encode()). It needs to build a string representing your entire object to just check if it's empty. There's the overhead of converting things to strings, but moreover it will need to convert a million things if your object has a million properties, while actually just looking at one will let you know that it is not empty.Erstwhile
@Jasper: There is not bigger overhead than checking object in a cycle for key values like in the most popular answer here :)Stowage
@Stowage the overhead is bigger, even if it might be (I'm not sure it is under every circumstance) in the same order of magnitude. However, that answer involves returning false as soon as a different property is found which makes the story is different all together...Erstwhile
B
21
function isEmpty(obj) {
  for(var i in obj) { return false; }
  return true;
}
Binturong answered 24/4, 2009 at 13:9 Comment(1)
That'll report also true, when, for instance, a JavaScript library extends Object with a method through the prototype chain, because that's enumerable and the for in statement loops through enumerable properties.Messroom
H
17

The correct answer is:

function isEmptyObject(obj) {
  return (
    Object.getPrototypeOf(obj) === Object.prototype &&
    Object.getOwnPropertyNames(obj).length === 0 &&
    Object.getOwnPropertySymbols(obj).length === 0
  );
}

This checks that:

  • The object's prototype is exactly Object.prototype.
  • The object has no own properties (regardless of enumerability).
  • The object has no own property symbols.

In other words, the object is indistinguishable from one created with {}.

Halpin answered 9/4, 2018 at 9:37 Comment(0)
N
15

The following example show how to test if a JavaScript object is empty, if by empty we means has no own properties to it.

The script works on ES6.

const isEmpty = (obj) => {
    if (obj === null ||
        obj === undefined ||
        Array.isArray(obj) ||
        typeof obj !== 'object'
    ) {
        return true;
    }
    return Object.getOwnPropertyNames(obj).length === 0;
};
console.clear();
console.log('-----');
console.log(isEmpty(''));           // true
console.log(isEmpty(33));           // true
console.log(isEmpty([]));           // true
console.log(isEmpty({}));           // true
console.log(isEmpty({ length: 0, custom_property: [] })); // false
console.log('-----');
console.log(isEmpty('Hello'));      // true
console.log(isEmpty([1, 2, 3]));    // true
console.log(isEmpty({ test: 1 }));  // false
console.log(isEmpty({ length: 3, custom_property: [1, 2, 3] })); // false
console.log('-----');
console.log(isEmpty(new Date()));   // true
console.log(isEmpty(Infinity));     // true
console.log(isEmpty(null));         // true
console.log(isEmpty(undefined));    // true
Nonillion answered 29/3, 2017 at 10:42 Comment(1)
Why exactly is isEmpty([1, 2, 3]) supposed to be true?Bedspread
L
14

jQuery have special function isEmptyObject() for this case:

jQuery.isEmptyObject({}) // true
jQuery.isEmptyObject({ foo: "bar" }) // false

Read more on http://api.jquery.com/jQuery.isEmptyObject/

Lumbricoid answered 25/1, 2011 at 14:25 Comment(0)
K
8

To really accept ONLY {}, the best way to do it in Javascript using Lodash is:

_.isEmpty(value) && _.isPlainObject(value)
Kropp answered 23/5, 2019 at 8:7 Comment(0)
W
6

Caveat! Beware of JSON's limitiations.

javascript:
  obj={  f:function(){}  };
  alert( "Beware!! obj is NOT empty!\n\nobj = {  f:function(){}  }" + 
               "\n\nJSON.stringify( obj )\n\nreturns\n\n" +
                        JSON.stringify( obj ) );

displays

    Beware!! obj is NOT empty!

    obj = {  f:function(){}  }

    JSON.stringify( obj )

    returns

    {}
Wiebmer answered 24/5, 2011 at 1:52 Comment(0)
N
5

Another alternative is to use is.js (14kB) as opposed to jquery (32kB), lodash (50kB), or underscore (16.4kB). is.js proved to be the fastest library among aforementioned libraries that could be used to determine whether an object is empty.

http://jsperf.com/check-empty-object-using-libraries

Obviously all these libraries are not exactly the same so if you need to easily manipulate the DOM then jquery might still be a good choice or if you need more than just type checking then lodash or underscore might be good. As for is.js, here is the syntax:

var a = {};
is.empty(a); // true
is.empty({"hello": "world"}) // false

Like underscore's and lodash's _.isObject(), this is not exclusively for objects but also applies to arrays and strings.

Under the hood this library is using Object.getOwnPropertyNames which is similar to Object.keys but Object.getOwnPropertyNames is a more thorough since it will return enumerable and non-enumerable properties as described here.

is.empty = function(value) {
    if(is.object(value)){
        var num = Object.getOwnPropertyNames(value).length;
        if(num === 0 || (num === 1 && is.array(value)) || (num === 2 && is.arguments(value))){
            return true;
        }
        return false;
    } else {
        return value === '';
    }
};

If you don't want to bring in a library (which is understandable) and you know that you are only checking objects (not arrays or strings) then the following function should suit your needs.

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

This is only a bit faster than is.js though just because you aren't checking whether it is an object.

Nihil answered 5/6, 2015 at 17:16 Comment(0)
C
5

It's weird that I haven't encountered a solution that compares the object's values as opposed to the existence of any entry (maybe I missed it among the many given solutions).
I would like to cover the case where an object is considered empty if all its values are undefined:

    const isObjectEmpty = obj => Object.values(obj).every(val => typeof val === "undefined")

    console.log(isObjectEmpty({}))                                 // true
    console.log(isObjectEmpty({ foo: undefined, bar: undefined })) // true
    console.log(isObjectEmpty({ foo: false,     bar: null }))      // false

Example usage

Let's say, for the sake of example, you have a function (paintOnCanvas) that destructs values from its argument (x, y and size). If all of them are undefined, they are to be left out of the resulting set of options. If not they are not, all of them are included.

function paintOnCanvas ({ brush, x, y, size }) {
  const baseOptions = { brush }
  const areaOptions = { x, y, size }
  const options = isObjectEmpty(areaOptions) ? baseOptions : { ...baseOptions, areaOptions }
  // ...
}
Crab answered 27/6, 2018 at 11:24 Comment(0)
I
5

Pure Vanilla Javascript, and full backward compatibility

function isObjectDefined (Obj) {
  if (Obj === null || typeof Obj !== 'object' ||
    Object.prototype.toString.call(Obj) === '[object Array]') {
    return false
  } else {
    for (var prop in Obj) {
      if (Obj.hasOwnProperty(prop)) {
        return true
      }
    }
    return JSON.stringify(Obj) !== JSON.stringify({})
  }
}

console.log(isObjectDefined()) // false
console.log(isObjectDefined('')) // false
console.log(isObjectDefined(1)) // false
console.log(isObjectDefined('string')) // false
console.log(isObjectDefined(NaN)) // false
console.log(isObjectDefined(null)) // false
console.log(isObjectDefined({})) // false
console.log(isObjectDefined([])) // false
console.log(isObjectDefined({a: ''})) // true
Impending answered 19/4, 2019 at 17:31 Comment(1)
isObjectDefined({ hasOwnProperty: null })Bedspread
M
5

Best one-liner solution I could find (updated):

isEmpty = obj => !Object.values(obj).filter(e => typeof e !== 'undefined').length;

console.log(isEmpty({}))                                        // true
console.log(isEmpty({a: undefined, b: undefined}))              // true
console.log(isEmpty({a: undefined, b: void 1024, c: void 0}))   // true

console.log(isEmpty({a: [undefined, undefined]}))               // false
console.log(isEmpty({a: 1}))                                    // false
console.log(isEmpty({a: ''}))                                   // false
console.log(isEmpty({a: null, b: undefined}))                   // false
Madrepore answered 21/4, 2020 at 19:44 Comment(4)
Greatest answer overlookedCastlereagh
@Damien, tbf the question is 11 years old & this answer was posted 2 weeks ago.Hydropathy
What if the object is like this: { 0 : null }, I am getting a key whose value is null. What to do in such cases?Negrillo
Checking Object.keys().length was already suggested on this question in 2009. https://mcmap.net/q/36101/-how-do-i-test-for-an-empty-javascript-object So this posted answer is half flawed and the other half redundant.Fraternal
M
5

IsEmpty Object, unexpectedly lost its meaning i.e.: it's programming semantics, when our famous guru from Yahoo introduced the customized non-enumerable Object properties to ECMA and they got accepted.

[ If you don't like history - feel free to skip right to the working code ]

I'm seeing lots of good answers \ solutions to this question \ problem. However, grabbing the most recent extensions to ECMA Script is not the honest way to go. We used to hold back the Web back in the day to keep Netscape 4.x, and Netscape based pages work and projects alive, which (by the way) were extremely primitive backwards and idiosyncratic, refusing to use new W3C standards and propositions [ which were quite revolutionary for that time and coder friendly ] while now being brutal against our own legacy.

Killing Internet Explorer 11 is plain wrong! Yes, some old warriors that infiltrated Microsoft remaining dormant since the "Cold War" era, agreed to it - for all the wrong reasons. - But that doesn't make it right!

Making use, of a newly introduced method\property in your answers and handing it over as a discovery ("that was always there but we didn't notice it"), rather than a new invention (for what it really is), is somewhat 'green' and harmful. I used to make such mistakes some 20 years ago when I still couldn't tell what's already in there and treated everything I could find a reference for, as a common working solution...

Backward compatibility is important !

We just don't know it yet. That's the reason I got the need to share my 'centuries old' generic solution which remains backward and forward compatible to the unforeseen future.

There were lots of attacks on the in operator but I think the guys doing that have finally come to senses and really started to understand and appreciate a true Dynamic Type Language such as JavaScript and its beautiful nature.

My methods aim to be simple and nuclear and for reasons mentioned above, I don't call it "empty" because the meaning of that word is no longer accurate. Is Enumerable, seems to be the word with the exact meaning.

function isEnum( x ) { for( var p in x )return!0; return!1 };

Some use cases:

isEnum({1:0})
true

isEnum({})
false

isEnum(null)
false

Thanks for reading!

Masker answered 8/9, 2021 at 9:52 Comment(0)
L
4

Sugar.JS provides extended objects for this purpose. The code is clean and simple:

Make an extended object:

a = Object.extended({})

Check it's size:

a.size()
Lemmons answered 16/8, 2012 at 9:46 Comment(0)
C
4

This one line code helps with fallback to older browsers too.

var a = {}; //if empty returns false
(Object.getOwnPropertyNames ? Object.getOwnPropertyNames(a).length !== 0 : (function(){ for(var key in a) break; return !!key })()) //Returns False

var a = {b:2}; //if not empty returns true
(Object.getOwnPropertyNames ? Object.getOwnPropertyNames(a).length !== 0 : (function(){ for(var key in a) break; return !!key })()) //Returns true

Object.getOwnPropertyNames is implemented in ECMA-5. the above line works in older browsers with a fallback function.


Another quick solution is checking the length property of Object.keys, Object.entries or Object.values

Knowledge article: Follow this SO post for detailed difference between Object.keys Vs Object.getOwnPropertyNames

Chrissy answered 20/10, 2014 at 11:28 Comment(0)
B
4

I know this doesn't answer 100% your question, but I have faced similar issues before and here's how I use to solve them:

I have an API that may return an empty object. Because I know what fields to expect from the API, I only check if any of the required fields are present or not.

For example:

API returns {} or {agentID: '1234' (required), address: '1234 lane' (opt),...}. In my calling function, I'll only check

if(response.data && response.data.agentID) { 
  do something with my agentID 
} else { 
  is empty response
}

This way I don't need to use those expensive methods to check if an object is empty. The object will be empty for my calling function if it doesn't have the agentID field.

Brana answered 20/2, 2020 at 23:29 Comment(0)
C
4

We can check with vanilla js with handling null or undefined check also as follows,

function isEmptyObject(obj) {
  return !!obj && Object.keys(obj).length === 0 && obj.constructor === Object;
}

//tests

isEmptyObject(new Boolean());  // false 
isEmptyObject(new Array());    // false 
isEmptyObject(new RegExp());   // false 
isEmptyObject(new String());   // false 
isEmptyObject(new Number());   // false 
isEmptyObject(new Function()); // false 
isEmptyObject(new Date());     // false
isEmptyObject(null);          // false
isEmptyObject(undefined);     // false
isEmptyObject({});            // true
Cupriferous answered 19/7, 2020 at 17:8 Comment(0)
S
3

I can't believe after two years of programming js it never clicked that empty objects and array's aren't falsey, the weirdest thing is it never caught me out.

this will return true if the input is falsey by default or if it's an empty object or array. the inverse is the trueish function

http://codepen.io/synthet1c/pen/pjmoWL

function falsish( obj ){
    if( (typeof obj === 'number' && obj > 0) || obj === true ){
        return false;
    }
    return !!obj
        ? !Object.keys( obj ).length
        : true;
}

function trueish( obj ){
    return !falsish( obj );
}

falsish({})           //=> true
falsish({foo:'bar'})  //=> false
falsish([])           //=> true
falsish(['foo'])      //=> false
falsish(false)        //=> true
falsish(true)         //=> false
// the rest are on codepen
Sclerotic answered 23/11, 2015 at 12:30 Comment(2)
@user1167442 The array you have provided is not empty, it's an array containing an empty array, so is not what I would describe as falshish. I'm not sure that it could be handled without adding recursion increasing the complexity of the basic function.Sclerotic
- I got it. I got here looking for a solution that would handle both scenarios elegantly, so though your code is fine; I was irritated that it didn't solve my problem :). U got up voted for solving the problem you were trying to solve.Sappington
D
2

As of jQuery 1.4 isEmptyObject() method checks both properties on the object itself and properties inherited from prototypes (in that it doesn't use hasOwnProperty). The argument should always be a plain JavaScript Object as other types of object (DOM elements, primitive strings/numbers, host objects) may not give consistent results across browsers. To determine if an object is a plain JavaScript object, use $.isPlainObject().

jQuery.isPlainObject({}) // true

jQuery.isPlainObject( "test" ) // false

Jquery api

Dairymaid answered 19/4, 2014 at 7:19 Comment(0)
R
1
export function isObjectEmpty(obj) {
  return (
    Object.keys(obj).length === 0 &&
    Object.getOwnPropertySymbols(obj).length === 0 &&
    obj.constructor === Object
  );
}

This include checking for objects containing symbol properties.

Object.keys does not retrieve symbol properties.

Rouleau answered 21/3, 2019 at 1:56 Comment(0)
A
1

Mostly what you want to know is, if the object has properties before using it. So instead of asking isEmpty and then always check the negation like if(!isEmpty(obj)) you can just test if the object is not null and has properties instead

export function hasProperties(obj): boolean {
  return obj && obj.constructor === Object && Object.keys(obj).length >= 1;
}
Auston answered 2/9, 2020 at 7:48 Comment(1)
hasProperties({ constructor: "where is your god now?" })Bedspread
B
0

I was returning an empty JSON response for an AJAX call and in IE8 jQuery.isEmptyObject() was not validating correctly. I added an additional check that seems to catch it properly.

.done(function(data)
{  
    // Parse json response object
    var response = jQuery.parseJSON(data);

    // In IE 8 isEmptyObject doesn't catch the empty response, so adding additional undefined check
    if(jQuery.isEmptyObject(response) || response.length === 0)
    {
        //empty
    }
    else
    {
        //not empty
    }
});
Bobodioulasso answered 6/6, 2014 at 17:58 Comment(0)
S
-1
    isEmpty = function(obj) {
      if (obj == null) return true;
      if (obj.constructor.name == "Array" || obj.constructor.name == "String") return obj.length === 0;
      for (var key in obj) if (isEmpty(obj[key])) return true;
      return false;
    }

This will check the emptiness of String, Array or Object (Maps).

Usage :

var a = {"a":"xxx","b":[1],"c":{"c_a":""}}
isEmpty(a); // true, because a.c.c_a is empty.
isEmpty("I am a String"); //false
Swanee answered 18/2, 2015 at 10:25 Comment(3)
isEmpty({}) gives FALSE here is testTaritariff
This answer should not have any upvotes whatsoever. isEmpty({}) will return false. isEmpty({a: '', b: 'I am not empty'}) will return trueDebra
Not to mention isEmpty({ constructor: null }) will throw an error.Bedspread
B
-1

isEmpty for value any type

/* eslint-disable no-nested-ternary */

const isEmpty = value => {
  switch (typeof value) {
    case 'undefined':
      return true;
    case 'object':
      return value === null
        ? true
        : Array.isArray(value)
        ? !value.length
        : Object.entries(value).length === 0 && value.constructor === Object;
    case 'string':
      return !value.length;
    default:
      return false;
  }
};
Bonnee answered 23/10, 2019 at 15:29 Comment(0)
S
-1
isEmptyObject(value) {
  return value && value.constructor === Object && Object.keys(value).length === 0;
}

The above code is enough to check the empty-ness of an Object.

A very good article is written at how-to-check-if-object-is-empty

Superstratum answered 1/6, 2021 at 10:9 Comment(3)
This looks pretty much like the accepted answerBogtrotter
sequence of check matters.Superstratum
isEmptyObject(Object.create({ constructor: Object, empty: "surely not" }))Bedspread
S
-2

Try Destructuring

const a = {};
const { b } = a;
const emptryOrNot = (b) ? 'not Empty' : 'empty';
console.log(emptryOrNot)
Scornful answered 8/11, 2017 at 11:6 Comment(2)
did you actually try this? Put anything in a and it still says emptyAltamirano
That is not how destructuring works. This will only work for objects containing an entry with a key 'b'Debra
M
-2

This is what I came up with, to tell if there are any non-null values in the object.

function isEmpty(obj: Object): Boolean {
    for (const prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            if (obj[prop] instanceof Object) {
                const rtn = this.isEmpty(obj[prop]);
                if (rtn === false) {
                  return false;
                }
            } else if (obj[prop] || obj[prop] === false) {
                return false;
            }
        }
    }
    return true;
}
Mouthy answered 14/8, 2018 at 21:49 Comment(0)
S
-3

Here is a fast, simple, function:

function isEmptyFunction () {
  for (const i in this) return false
  return true
}

Implemented as a getter:

Object.defineProperty(Object.prototype, 'isEmpty', { get: isEmptyFunction })

console.log({}.isEmpty) // true

Implemented as a separate function:

const isEmpty = Function.prototype.call.bind(isEmptyFunction)

console.log(isEmpty({})) // true
Slesvig answered 15/3, 2012 at 3:52 Comment(2)
Without Object.hasOwnProperty, this function will always return true (the function is called isEmpty, but returns true when it's not empty, by the way...). Also, the function will not invoke itself automatically. Add () after obj.isEmpty.Giana
Also, after just stumbling across this you would probably want to swap the return true/false statements. The function 'isEmpty' should return false once it finds a property, because that means that it is not empty. Semantics, but would probably be a good idea.Tyndale
N
-4

Perfect and failsafe solution

I think the first accepted solution works in most cases but is not Failsafe.

The better and failsafe solution will be.

function isEmptyObject() { 
  return toString.call(obj) === "[object Object]" 
  && Object.keys(obj).length === 0;
}

or in ES6/7

const isEmptyObject = () => toString.call(obj) === "[object Object]" 
  && Object.keys(obj).length === 0;

With this approach if the obj is set to undefined or null, the code does not break. and return null.

Nolde answered 15/11, 2019 at 18:6 Comment(3)
You are checking if an object is empty with fixed strings and hacks/irregular practices like "toString.call(obj). This is just bad practice and code you dont wanna see in a codebase. There are much better and clean solutions that make sense just by reading them. This does not make sense while reading it, it's a hack.Potsdam
also this does not consider non-enumerable properties or inherited onesOligochaete
@Eksapsy: It’s how we used to check for arrays before Array.isArray existed, and there’s no Object.isObject, so not that irregular.Botryoidal

© 2022 - 2024 — McMap. All rights reserved.