Object.is() vs. Strict Equality in JavaScript

Hero image for Object.is() vs. Strict Equality in JavaScript. Image by Nicole Wilcox.
Hero image for 'Object.is() vs. Strict Equality in JavaScript.' Image by Nicole Wilcox.

Most of the time, strict equality does exactly what we want:

valueA === valueB

It is familiar, concise, and far safer than the loose equality operator in ordinary application code.

That is why Object.is() can seem unnecessary at first. Why add another equality check if === is already the sensible choice?

The answer is that Object.is() behaves differently in two specific edge cases:

  • NaN
  • signed zero, meaning +0 and 0

For daytoday work, that difference is not constantly important. Still, understanding it makes your mental model of JavaScript equality much sharper.


Strict Equality is Still the Default Tool

Let us say that clearly first.

For most comparisons in frontend code, === is exactly right:

const isAdmin = role === 'admin';const isPublished = status === 'published';const hasSameId = currentId === selectedId;

Nothing about Object.is() changes that.

The interesting part is what happens at the edges.


NaN breaks the obvious expectation

This is the first strange case:

console.log(NaN === NaN);

That returns false.

If you have not met this before, it feels absurd. The same value does not equal itself?

With Object.is():

console.log(Object.is(NaN, NaN));

the result is true.

That is one of the main reasons the method exists.


Signed Zero is the Other Difference

JavaScript distinguishes between +0 and 0 in certain lowlevel numeric situations.

Strict equality treats them as the same:

console.log(+0 === -0);

That returns true.

Object.is() does not:

console.log(Object.is(+0, -0));

That returns false.

If you rarely work with signed zero directly, this may seem almost comically niche. In much everyday code, it is. But it is still part of the language's equality story.


Everywhere Else, the Behaviour Matches What You Would Expect

For ordinary values:

console.log(Object.is(3, 3));console.log(Object.is('hello', 'hello'));console.log(Object.is(true, true));console.log(Object.is({}, {}));

the results are broadly in line with strict equality expectations:

  • primitives compare by value
  • separate object references are not equal

So the real distinction is not that Object.is() reinvents equality completely. It refines it in a couple of awkward places.


It is Also Worth Separating This from Loose Equality

Because JavaScript has more than one comparison style, people can end up mentally blending the wrong things together.

Object.is() is not an alternative to loose equality in the way === is. It is not there to help with coercive comparisons such as:

0 == '0';

That is a completely different discussion.

The useful mental split is:

  • == performs coercion and is best avoided in most application code
  • === is the normal strict comparison tool
  • Object.is() is a more exact sameness check for a couple of unusual edge cases

Once you keep those roles separate, the method feels far less mysterious.


Why NaN matters more than 0 for most developers

You are much more likely to encounter NaN in practical JavaScript:

  • failed parsing
  • invalid maths
  • divisionrelated bugs
  • unexpected input conversion

That means Object.is() occasionally becomes useful when you are doing very deliberate numeric work and want an equalitystyle check that treats NaN as matching itself.

Even so, when the goal is specifically "is this value NaN?", Number.isNaN() is usually a clearer tool than Object.is(value, NaN).


The Signed Zero Case Matters Mainly in Technical Code

Most productfacing UI logic will never care whether a zero is positive or negative. If you are showing a shopping basket total or checking whether a field is empty, +0 versus 0 is not the battle you are fighting.

Where it can matter is in lowerlevel numeric work, calculations that preserve sign, or code that is intentionally mirroring the language's exact sameness semantics. That is why Object.is() tends to feel more relevant in library code than in ordinary business rules.


So when would you use Object.is() in real code

A few cases stand out:

  • lowlevel equality helpers
  • memoisation or caching logic
  • changedetection code
  • library internals where exact sameness rules matter

For example, if a utility needs to know whether two values are identical under the language's most precise sameness rules, Object.is() is a sensible choice.

That is partly why you see it discussed in relation to framework internals and state comparison logic.


What Object.is() is not

It is not:

  • a deep equality function
  • a replacement for everyday === comparisons
  • a magical object comparison helper

This still returns false:

console.log(Object.is({ name: 'Ellie' }, { name: 'Ellie' }));

The two objects are different references.

That point is worth stressing because people sometimes see the method name and assume it must somehow compare object contents. It does not.


This is Really About Precision, Not Convenience

=== is convenient and usually correct.

Object.is() is slightly more precise in a very specific technical sense.

That precision matters when the edge cases matter. Otherwise, it can just be unnecessary noise.

If a comparison is about ordinary strings, booleans, IDs, or status values, === keeps the code simpler. Replacing all equality checks with Object.is() would usually make the codebase feel more selfconscious without improving it.


A Good Rule of Thumb

Use === by default.

Reach for Object.is() when:

  • you explicitly care about NaN comparing equal to itself
  • you need to distinguish +0 from 0
  • you are implementing lowlevel comparison behaviour rather than ordinary business logic

That is the honest place for the method.


Understanding It is Still Worthwhile

Even if you do not use Object.is() every week, knowing about it sharpens how you think about JavaScript equality overall.

It reminds us that equality is not one giant simple idea in the language. There are a few subtly different comparison rules, and they exist because the awkward corners of numbers forced the language to make choices somewhere.

Seen that way, Object.is() is less a competing equality operator and more a precise diagnostic tool for sameness.

And in JavaScript, it is usually worth knowing where the sharp edges live, even if you do not touch them often.


Categories:

  1. Development
  2. Front‑End Development
  3. Guides
  4. JavaScript