Object.is()

Compares two values for same-value equality, treating NaN as equal and +0 as distinct from -0.

Signature
Object.is(value1, value2)
  • Added in JavaScript ES2015

Parameters

ParameterTypeDescription
$value1anyThe first value to compare.
$value2anyThe second value to compare.

Return value

booleantrue if the two arguments are the same value, otherwise false.

Object.is() implements the SameValue algorithm. It behaves exactly like === except in two places:

Comparison=====Object.is()
NaN, NaNfalsefalsetrue
0, -0truetruefalse
'1', 1truefalsefalse

When to reach for it

  • Writing a generic equality helper, a memoisation cache or a change detector where NaN is a legitimate value and must compare equal to itself.
  • Numerical code where the sign of zero carries meaning — -0 and 0 differ in 1 / x and in atan2-style geometry.

What trips people up

Object.is() does not do structural comparison. Two objects are the same only if they are the same reference, so Object.is([], []) is false just as [] === [] is. The name suggests deep equality to newcomers; it offers none.

It is also not the same as Array.prototype.includes()' comparison, which uses SameValueZero: includes() finds NaN but treats 0 and -0 as equal, while Object.is() separates them.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Detect NaN in a value without the coercion quirks of the global isNaN()
  • Skip a re-render or a cache write when the new value is genuinely identical to the old one
  • Assert that a math routine returned -0 rather than 0

Frequently asked questions

What is the difference between Object.is and ===?

They agree on everything except two cases: Object.is(NaN, NaN) is true where === is false, and Object.is(0, -0) is false where === is true.

Does Object.is compare objects deeply?

No. It compares object references, so Object.is({}, {}) is false; use a deep-equal helper or compare serialised forms for structural comparison.

Should I use Object.is instead of === everywhere?

No. === is clearer and faster for ordinary code; reach for Object.is() only when NaN or the sign of zero must be handled correctly.

More examples

A change detector that survives NaN

With !==, a stored NaN always looks different from an incoming NaN, so a UI would re-render forever. Object.is() reports no change, while still flagging the sign flip from 0 to -0 that some numeric code cares about.

Example · javascript
function changed(prev, next) {
  return !Object.is(prev, next);
}

let state = NaN;
console.log(changed(state, NaN));      // false — nothing to update
console.log(state !== NaN);            // true — the naive check misfires

console.log(changed(5, 5));            // false
console.log(changed(5, 6));            // true
console.log(changed(0, -0));           // true — sign flip counts

Three flavours of equality on the same data

indexOf() uses strict equality and cannot find NaN at all. includes() and Set use SameValueZero, which finds NaN but folds -0 into 0. Only Object.is() keeps both distinctions, which is why it is the one to use when the sign of zero matters.

Example · javascript
const values = [NaN, 0, -0];

console.log(values.indexOf(NaN));        // -1  (uses ===)
console.log(values.includes(NaN));       // true (SameValueZero)
console.log(values.findIndex((v) => Object.is(v, -0))); // 2 (SameValue)

console.log(new Set([0, -0]).size);      // 1 — SameValueZero merges them
console.log(Object.is(0, -0));           // false — SameValue does not

Discussion

  • Be the first to comment on this lesson.