ChatGPT解决这个技术问题 Extra ChatGPT

How do I test for an empty JavaScript object?

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.

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

var a = {};

How can I check whether that's the case?


1
16 revs, 16 users 51%

ECMA 5+:

// because Object.keys(new Date()).length === 0;
// we have to do some additional check
obj // 👈 null and undefined check
&& Object.keys(obj).length === 0
&& Object.getPrototypeOf(obj) === Object.prototype

Note, though, that this creates an unnecessary array (the return value of keys).

Pre-ECMA 5:

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

  return JSON.stringify(obj) === JSON.stringify({});
}

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

Object.keys(new Date()).length === 0; so this answer can be misleading.
Why do we need to check obj.contructor===Object in ECMA5+ code ? We can only use this code obj // 👈 null and undefined check && Object.keys(obj).length === 0
The comment right above yours literally explains why =) There are a million different objects, so you want to make sure to only test for "actual object primitives", i.e. objects whose constructor is not some extension of Object.
This returns true for an object that is not empty, but all its keys are symbols.
@Wronski Yes, potentially, and it’s already in the answer. It’s not a very good solution, though (slow, no more reliable and sometimes less).
m
mikemaccana

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

This works fine, or more simply: function isEmpty(object) { for(var i in object) { return true; } return false; }
Shouldnt true and false be reversed in this function?
@namtax: no - the function is named isEmpty(), so it should return false if it has a property
@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; })(); }
Alernatively: function isObjectEmpty(obj) { for (const i in obj) return false; return true; }
U
Unmitigated

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


This won't work if you (or any plugin) modified Object.prototype.
note that this works fine for the question asked, {}, but that jQuery.isEmptyObject([]) === true, presumably because an empty list is iterable.
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.
A
Akaisteph7

Performance

Today 2020.01.17, I performed tests on macOS High Sierra 10.13.6 on Chrome v79.0, Safari v13.0.4, and Firefox v72.0; for the chosen solutions.

Conclusions

Solutions based on for-in (A, J, L, M) are fastest

Solutions based on JSON.stringify (B, K) are slow

Surprisingly, the solution based on Object (N) is also slow

NOTE: This table does not match the photo below.

https://i.stack.imgur.com/yqmYR.png

Details

There are 15 solutions presented in the snippet below. If you want to run a performance test on your machine, click HERE. This link was updated 2021.07.08, but tests originally were performed here - and results in the table above came from there (but now it looks like that service no longer works).

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" || !Boolean(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) { for (var prop in obj) { if (obj.hasOwnProperty(prop)) { return false; } } return JSON.stringify(obj) === JSON.stringify({}); } function L(obj) { for (var prop in obj) { if (obj.hasOwnProperty(prop)) return false; } return true; } function M(obj) { for (var k in obj) { if (obj.hasOwnProperty(k)) { return false; } } return true; } 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; })()); } 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);

https://i.stack.imgur.com/ma99z.png


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 fyi
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/2
@Christian Matthew Okay, (o => { for(let k in o) return false; return true; })(obj)
G
Gabriel GM

You can use Underscore.js.

_.isEmpty({}); // true

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.
If adding the entire dependency is mortifying to your super-performance dependent application, you can install just _.isEmpty: npm i lodash.isempty
e
es cologne
if(Object.getOwnPropertyNames(obj).length === 0){
  //is empty
}

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


This includes non-enumerable properties, in case you care.
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.
Object.getOwnPropertyNames(new Date()).length === 0; so this answer can be misleading.
s
sktguha

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

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

This is slow and speed matters for this kind of utility. Quick perf test here: jsperf.com/empty-object-test
This is a very slow option - I suggest to use the (for...in) option instead
And it doesn't work for objects that contain functions.
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.
Please note that JSON.stringify(new Error('gotcha')) === '{}' is true
p
peterh

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

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)
E
Erin

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


Where does the keys property come from?
It's a standard method in ECMAScript 5.1
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!
Object.keys(new Date()).length === 0; so this answer can be misleading.
@scravy 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/…
t
tim-montague

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?


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?
k
kiranvj

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

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)
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") {...}
C
CertainPerformance

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.


Object.keys(new Date()).length === 0; so this answer can be misleading.
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.
f
franzlorenzon

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. 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.


toSource() is non-standard and doesn't work in IE or Opera (and potentially other browsers I didn't check)
@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!
@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...
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.
@Thevs 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...
L
Lightness Races in Orbit
function isEmpty(obj) {
  for(var i in obj) { return false; }
  return true;
}

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.
L
LostMyGlasses

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


佚名

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/


J
Jesse

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 {}.


E
Ekim

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

    {}

s
starikovs

In addition to Thevs answer:

var o = {};
alert($.toJSON(o)=='{}'); // true

var o = {a:1};
alert($.toJSON(o)=='{}'); // false

it's jquery + jquery.json


I don't like using JSON because it can't work with circular object structures.
If your page loads jQuery then use $.isEmptyObject(), don't waste cycles with non-obvious conversions.
E
Ericgit

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 && empty.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


m
mikemaccana

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

J
João Pimentel Ferreira

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


A
Anthony D'Amato

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

_.isEmpty(value) && _.isPlainObject(value)

B
Bekim Bacaj

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!


It's disgusting what people have done to the web
R
Ran Marciano

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


Greatest answer overlooked
@Damien, tbf the question is 11 years old & this answer was posted 2 weeks ago.
What if the object is like this: { 0 : null }, I am getting a key whose value is null. What to do in such cases?
Checking Object.keys().length was already suggested on this question in 2009. stackoverflow.com/a/679937/2943403 So this posted answer is half flawed and the other half redundant.
C
Community

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.


J
Juan Vieira

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.


g
ganesh phirke

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


0
010011100101

I liked this one I came up with, with the help of some other answers here. Thought I'd share it.

Object.defineProperty(Object.prototype, 'isEmpty', { get() { for(var p in this) { if (this.hasOwnProperty(p)) {return false} } return true; } }); let users = {}; let colors = {primary: 'red'}; let sizes = {sm: 100, md: 200, lg: 300}; console.log( '\nusers =', users, '\nusers.isEmpty ==> ' + users.isEmpty, '\n\n-------------\n', '\ncolors =', colors, '\ncolors.isEmpty ==> ' + colors.isEmpty, '\n\n-------------\n', '\nsizes =', sizes, '\nsizes.isEmpty ==> ' + sizes.isEmpty, '\n', '' );


R
Ran Marciano

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