How do you reliably determine whether an object is empty?
TL;DR
First define what “empty” means. For the common case “no own enumerable string-keyed properties,” use Object.keys(obj).length === 0. If symbol or non-enumerable own keys should count, use Reflect.ownKeys(obj).length === 0. Validate the input separately if null, primitives, arrays, maps, or sets are not valid inputs.
const isEmpty = (obj) => Object.keys(obj).length === 0;const obj = {};console.log(isEmpty(obj)); // true
How do you reliably determine whether an object is empty?
Using Object.keys()
The most common and reliable way to check if an object is empty is by using Object.keys(). This method returns an array of the object's own enumerable property names. If the length of this array is zero, the object is empty.
const isEmpty = (obj) => Object.keys(obj).length === 0;const obj1 = {};const obj2 = { key: 'value' };console.log(isEmpty(obj1)); // trueconsole.log(isEmpty(obj2)); // false
Using Object.entries()
Another method is to use Object.entries(), which returns an array of the object's own enumerable property [key, value] pairs. If the length of this array is zero, the object is empty.
const isEmpty = (obj) => Object.entries(obj).length === 0;const obj1 = {};const obj2 = { key: 'value' };console.log(isEmpty(obj1)); // trueconsole.log(isEmpty(obj2)); // false
Using Object.values()
Similarly, you can use Object.values(), which returns an array of the object's own enumerable property values. If the length of this array is zero, the object is empty.
const isEmpty = (obj) => Object.values(obj).length === 0;const obj1 = {};const obj2 = { key: 'value' };console.log(isEmpty(obj1)); // trueconsole.log(isEmpty(obj2)); // false
Using a for...in loop
You can also use a for...in loop. Because it visits enumerable properties from both the object and its prototype chain, use Object.hasOwn() to count only the object's own properties.
const isEmpty = (obj) => {for (const key in obj) {if (Object.hasOwn(obj, key)) {return false;}}return true;};const obj1 = {};const obj2 = { key: 'value' };const childObj = Object.create(obj2); // Inherit from obj2console.log(isEmpty(obj1)); // trueconsole.log(isEmpty(obj2)); // falseconsole.log(isEmpty(childObj)); // true (has no own properties)console.log(childObj.key); // Output: 'value' (still has the inherited property)
Edge cases
- Prototype properties: The methods above only check for the object's own properties, not properties inherited from its prototype.
- Non-enumerable properties: These methods do not account for non-enumerable properties.
- Symbol properties:
Object.keys(),Object.values(),Object.entries(), andfor...inignore symbol keys.Reflect.ownKeys()includes both string and symbol own keys, whether enumerable or not. - Other collection types: For
MapandSet, use.size. For arrays, decide whether “empty” means.length === 0or no own keys. Do not use a plain-object helper indiscriminately. - Own-property checks: Calling
obj.hasOwnProperty(key)directly can fail if the object has anullprototype or shadowshasOwnProperty. PreferObject.hasOwn(obj, key)(Baseline across modern browsers since 2022) orObject.prototype.hasOwnProperty.call(obj, key).
Further reading
- MDN Web Docs: Object.keys()
- MDN Web Docs: Object.entries()
- MDN Web Docs: Object.values()
- MDN Web Docs: for...in