jsguides

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

ParameterTypeDefaultDescription
value1anyFirst value to compare
value2anySecond 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 === NaNfalsetrue
0 === -0truefalse

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