JavaScript gives us multiple ways to compare values: ==
, ===
, and Object.is
.
Most of the time ===
is good enough, but it has some edge cases where results can be⦠surprising.
Thatβs where Object.is
comes in.
π When was Object.is
introduced?
- Introduced in ES6 (ECMAScript 2015).
- Designed as a more reliable equality check than
===
.
π€ Why do we need Object.is
?
Strict equality (===
) works in most cases, but fails in two tricky ones:
- NaN comparison
NaN === NaN // false β
Object.is(NaN, NaN); // true β
- +0 vs -0
+0 === -0 // true β
Object.is(+0, -0); // false β
So Object.is
was introduced to fix these quirks and make equality checks more precise.
π Comparing ==
, ===
, and Object.is
Comparison |
== (loose) |
=== (strict) |
Object.is |
---|---|---|---|
Type coercion | β Yes | β No | β No |
NaN === NaN |
false | false | β true |
+0 === -0 |
true | true | β false |
Normal values | Works w/ coercion | Works strictly | Same as === (except above two cases) |
β
Where should you use Object.is
?
- Detecting NaN values
const value = 0 / 0; // NaN
console.log(Object.is(value, NaN)); // true
- Differentiating +0 and -0
console.log(Object.is(+0, -0)); // false
-
Shallow equality checks
Frameworks like React use
Object.is
to compare props/state and avoid unnecessary updates.
π Real-world usage
1. React state updates
React uses Object.is
internally when checking if a new state value is different from the old one.
const [count, setCount] = useState(NaN);
// This wonβt trigger a re-render
setCount(NaN); // Object.is(NaN, NaN) === true
If React only used ===
, this would trigger a render unnecessarily.
2. React.memo shallow prop comparison
React.memo
uses shallow equality with Object.is
under the hood.
const MyComponent = React.memo(({ value }) => {
console.log("Rendered");
return <div>{value}</div>;
});
<MyComponent value={NaN} /> // Rendered
<MyComponent value={NaN} /> // Not rendered again β
This prevents wasted renders when props are effectively βthe same.β
π Conclusion
Object.is
is a small but powerful addition introduced in ES6. It behaves like ===
in most cases, but with two important differences:
- It considers
NaN
equal toNaN
. - It treats
+0
and-0
as different.
These differences make it a reliable choice for edge cases where strict equality falls short.
While you might not use it every day, it plays a crucial role in libraries like React, ensuring accurate comparisons and avoiding unnecessary work.
Top comments (1)
Thanks for sharing this! Thanks to the very specific handling of numeric edge cases versus strict equality, it's a convenient tool for certain checks.
I would recommend
Number.isNaN()
forNaN
checks when we know we might have aNaN
. We shouldn't really ever write aNaN
for comparison sake, but especially in places like React where we might be comparing a previous value to a current one, usingObject.is()
would ensure the expected behavior.