Object.is()
Object.is(value1, value2) Object.is() compares two values for strict equality with subtle differences from the === operator. Unlike ===, it treats NaN as equal to itself and distinguishes between positive and negative zeros. This method is particularly useful when you need exact equality semantics, such as in polyfills or when working with values that have special zero representations.
Syntax
Object.is(value1, value2)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| value1 | any | — | First value to compare |
| value2 | any | — | Second value to compare |
The two parameters are symmetric — swapping value1 and value2 produces the same result. Unlike the loose equality operator (==), Object.is() never coerces types, so Object.is(1, '1') is always false.
Examples
Basic usage
Object.is(1, 1);
// true
Object.is(1, '1');
// false (different types)
Object.is(NaN, NaN);
// true (=== returns false)
Object.is() treats NaN as equal to itself — the most common reason developers reach for this method over ===. The other difference concerns how JavaScript represents zero internally: the IEEE 754 floating-point standard defines both a positive zero and a negative zero, and Object.is() can tell them apart.
Zero handling
Object.is(0, -0);
// false (=== returns true)
Object.is(-0, -0);
// true
Object.is(+0, +0);
// true
Object.is(0, 0);
// true
The signed-zero distinction rarely matters outside of physics simulations and graphics calculations where the sign of zero carries directional meaning. For everyday value comparisons, the NaN behaviour is the feature you are most likely to use. Object identity checks follow the same rules as === — two objects are equal only if they are the same reference, regardless of their contents.
Object identity
const obj = {};
Object.is(obj, obj);
// true (same reference)
Object.is({}, {});
// false (different objects)
const arr = [];
Object.is(arr, arr);
// true
Common Patterns
Use Object.is() when you need precise equality checking, especially when dealing with NaN comparisons or when the distinction between positive and negative zero matters. The method implements the SameValue algorithm, which is also what Object.defineProperty uses internally for descriptor comparisons:
// Safe NaN check (Number.isNaN also works, but Object.is works too)
function isNaN(value) {
return Object.is(value, NaN);
}
// Checking for signed zero in physics calculations
function hasNegativeZero(n) {
return Object.is(n, -0);
}
// Custom equality for libraries that need === semantics but with NaN handling
function deepEqual(a, b) {
if (a === b) return true;
if (Object.is(a, b)) return true;
// ... more complex comparison
}
Object.is() vs ===
The two operators differ in exactly two cases:
| Comparison | === | Object.is() |
|---|---|---|
NaN === NaN | false | true |
0 === -0 | true | false |
For all other values, Object.is(a, b) and a === b produce the same result. In practice, === is almost always what you want. Use Object.is() when you specifically need the SameValue algorithm — most commonly when implementing custom equality functions or polyfilling collection behaviour.
When to use Object.is()
The canonical use case is detecting NaN in a collection or state without reaching for Number.isNaN:
function containsNaN(arr) {
return arr.some(x => Object.is(x, NaN));
}
console.log(containsNaN([1, NaN, 3])); // true
console.log(containsNaN([1, 2, 3])); // false
Number.isNaN(x) is also fine for this, but Object.is(x, NaN) makes the intent explicit: “is this value exactly NaN, not just any non-numeric value?”
The -0 distinction matters in directional calculations, physics simulations, or any code where the sign of zero carries meaning:
function isNegativeZero(x) {
return Object.is(x, -0);
}
console.log(isNegativeZero(0)); // false
console.log(isNegativeZero(-0)); // true
console.log(isNegativeZero(-1)); // false
SameValue vs SameValueZero
Object.is() implements the SameValue algorithm. A closely related algorithm called SameValueZero is used by Map, Set, Array.prototype.includes, and Array.prototype.indexOf. SameValueZero treats +0 and -0 as equal (same as ===), whereas SameValue (Object.is) treats them as different. Both algorithms treat NaN as equal to itself. Keep this in mind when writing custom equality logic that needs to match the behaviour of built-in collections.
How React uses Object.is() for state comparisons
React’s useState and useEffect hooks, as well as Redux’s selector memoisation, use Object.is() to decide whether values have changed between renders. This is why shallow equality checks on objects always return false for new object references — even if the contents are identical — and why setting state to the same primitive value avoids a re-render. Understanding Object.is() semantics explains much of React’s re-render behaviour.
See Also
- Object.seal() — Seal object
- Object.keys() — Get array of object keys