JS: Check if an object is empty

The problem: we want to check if an object is empty.
Spoiler: simply checking for null
is not enough.
Null and undefined
First thing we can do for all types of object is to check if
a variable contains null
or undefined
:
if (a === null || a === undefined) {
return true
}
Check if an object has any properties
Then, we need to check most obvious case - our object is
not null or undefined, but it is has a {}
form. The problem is
that we can’t check for {}
directly, because javascript
compares objects by their reference:
// Prints "Not empty!"
const a = {}
if (a == {}) {
console.log("Empty")
} else {
console.log("Not empty!")
}
To check if an object has a property, we can iterate over all
its properties (including prototype chain) and use Object.hasOwnProperty
to check if a property is a target object’s property:
for (key in a) {
if (Object.hasOwnProperty(key)) {
return false;
}
}
We need to find at least one own property to know that the object is not empty, so we return false as soon as we find one.
We can also use Object.keys()
function to get object’s own keys:
if (Object.keys(a).length === 0) {
return false;
}
Arrays
Well done with “classic” objects, but arrays are objects too, and our previous method doesn’t work:
let a = [];
// Prints "[]"
console.log(Object.keys(a));
// Prints nothing
for (key in a) {
console.log(key)
}
Instead, we can check Array’s length
property:
if (Array.isArray(a) && a.length === 0) {
return true
}
We used isArray function to check if the target object is an array.
Maps and Sets
Maps and Sets are also objects, and they have a size
function that
returns the count of elements they contain, but they don’t have something like
isArray
, so we’re going to use Object.prototype.toString.
Object.prototype.toString() returns “[object Type]”, where Type is the object type. If the object has a
Symbol.toStringTag
property whose value is a string, that value will be used as the Type. Many built-in objects, including Map and Symbol, have aSymbol.toStringTag
Object.prototype.toString().call()
returns the object’s type, and we
can use it for maps and sets:
const tag = Object.prototype.toString().call(a);
if (a === "[object Set]" || a === "[object Map"]) {
return a.size() === 0;
}