Reputation: 39317
After an AJAX request, sometimes my application may return an empty object, like:
var a = {};
How can I check whether that's the case?
Upvotes: 3889
Views: 4349699
Reputation: 19258
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. Date
s), 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.isEmptyObject({}); // true
_.isEmpty({}); // true
_.isEmpty({}); // true
Hoek:
Hoek.deepEqual({}, {}); // true
Ext.Object.isEmpty({}); // true
angular.equals({}, {}); // true
R.isEmpty({}); // true
Upvotes: 7540
Reputation: 92627
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.
for-in
(A, L) are fast or fastest on all browsersJSON.stringify
(B) is slowest on all browsersThere solutions are presented in the snippet below. If you want to run a performance test on your machine, click
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>
Upvotes: 411
Reputation: 7103
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.
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) === '{}';
}
jQuery.isEmptyObject(obj);
_.isEmpty(obj);
Upvotes: 38
Reputation: 6995
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:
Object.prototype
.In other words, the object is indistinguishable from one created with {}
.
Upvotes: 17
Reputation: 2048
There is a simple way if you are on a newer browser.
Object.keys(obj).length === 0
Upvotes: 104
Reputation: 34147
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;
Update
OR
you can use the jQuery implementation of isEmptyObject
function isEmptyObject(obj) {
var name;
for (name in obj) {
return false;
}
return true;
}
Upvotes: 34
Reputation: 5955
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!
Upvotes: 6
Reputation: 6018
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
Upvotes: -1
Reputation: 169723
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;
}
Upvotes: 1476
Reputation: 105
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
Upvotes: 6
Reputation: 2192
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
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 }
// ...
}
Upvotes: 6
Reputation: 11411
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.
Upvotes: 39
Reputation: 919
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;
}
Upvotes: 0
Reputation: 473
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
Upvotes: 3
Reputation: 10496
For those of you who have the same problem but use jQuery, you can use jQuery.isEmptyObject.
Upvotes: 592
Reputation: 4269
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 ofObject.keys
,Object.entries
orObject.values
Knowledge article: Follow this SO post for detailed difference between Object.keys Vs Object.getOwnPropertyNames
Upvotes: 3
Reputation: 203
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.
Upvotes: 4
Reputation: 1759
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
Upvotes: -3
Reputation: 1390
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.
Upvotes: -5
Reputation: 2381
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:
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?
Upvotes: 51
Reputation: 616
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;
}
};
Upvotes: -1
Reputation: 758
To really accept ONLY {}
, the best way to do it in Javascript using Lodash is:
_.isEmpty(value) && _.isPlainObject(value)
Upvotes: 8
Reputation: 16292
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
Upvotes: 5
Reputation: 2531
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.
Upvotes: 1
Reputation: 67
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;
}
Upvotes: -2
Reputation: 73988
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
Upvotes: 15
Reputation: 509
Try Destructuring
const a = {};
const { b } = a;
const emptryOrNot = (b) ? 'not Empty' : 'empty';
console.log(emptryOrNot)
Upvotes: -2
Reputation: 4574
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;
}
Upvotes: 64
Reputation: 6282
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
Upvotes: 3