How to Check if a Value is a Plain Object in JavaScript
In JavaScript, checking if a value is a "plain" object—meaning an object literal ({...}) or created with new Object()—is not as straightforward as it seems. This is because the typeof operator famously returns 'object' for several different types, including arrays and null.
This guide will teach you the modern, standard, and most reliable method for accurately determining if a value is a plain object. You will also learn why other common approaches, like instanceof, are not suitable for this task.
The Core Problem: The Ambiguity of typeof
The typeof operator is often the first tool developers reach for, but it can be misleading. It returns 'object' for multiple types, not just plain objects.
console.log(typeof {}); // Output: "object" (Correct)
console.log(typeof []); // Output: "object" (This is an array!)
console.log(typeof null); // Output: "object" (This is null!)
console.log(typeof new Date()); // Output: "object" (This is a Date object!)
Because of this behavior, a simple typeof value === 'object' check is not sufficient and will lead to bugs.
The Modern Solution (Recommended): A Three-Step Check
The most reliable way to check for a plain object is to perform a series of checks that explicitly rule out the other types that typeof misidentifies.
A value is a plain object if and only if:
- Its
typeofis'object'. - It is not
null. - It is not an
Array.
It's a best practice to encapsulate this logic in a reusable function.
function isObject(value) {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
So the solution is the following:
function isObject(value) {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
// Example Usage:
console.log(isObject({ a: 1 })); // Output: true
console.log(isObject(new Object())); // Output: true
console.log(isObject([1, 2, 3])); // Output: false
console.log(isObject(null)); // Output: false
console.log(isObject('hello')); // Output: false
A Robust Alternative: Object.prototype.toString
For a highly precise type check, you can use Object.prototype.toString.call(). This method returns a string that represents the internal [[Class]] of the value, which is a more reliable way to distinguish between object-like types.
Solution:
function isObject(value) {
return Object.prototype.toString.call(value) === '[object Object]';
}
// Example Usage:
console.log(isObject({})); // Output: true
console.log(isObject([])); // Output: false (returns '[object Array]')
console.log(isObject(null)); // Output: false (returns '[object Null]')
While this method is very accurate, the three-step typeof check is often considered more readable and is more common in modern codebases.
Methods to Avoid
You might see other methods used for this check, but they are generally flawed.
instanceof Object: This is unreliable. It returnstruefor arrays ([] instanceof Objectistrue) andfalsefor objects created withObject.create(null).lodash.isObject(): The Lodash library'sisObjectfunction is much broader. It returnstruefor almost any object-like value, including arrays, functions, andDateobjects, which is not what you want when checking for a plain object.
Conclusion
Accurately checking if a value is a plain object requires you to be explicit and handle JavaScript's quirks.
- The recommended best practice is the three-step check that combines
typeof, anullcheck, andArray.isArray():typeof value === 'object' && value !== null && !Array.isArray(value) - The
Object.prototype.toString.call()method provides a very robust, albeit more verbose, alternative. - Avoid using
instanceof Object, as its behavior is inconsistent and not suitable for this task.