Don't Trust ==: JavaScript's Weird Comparison Truths (== vs === vs Object.is)
Use === as the default, and switch to Object.is only when you need to handle NaN or signed zeros (+0 vs -0) precisely. Avoid == at all costs.
Don't Trust ==: JavaScript's Weird Comparison Truths
Always use === as your default comparison operator. Only switch to Object.is when you need to handle NaN or signed zeros (+0 vs -0) precisely. Avoid == to prevent unexpected type coercion.
Background: The Chaos of Type Coercion
The double equals ( ==) operator attempts to compare values by forcibly converting them to the same type. This leads to infamous "JavaScript quirks" where empty arrays equal zero, but non-empty strings might not.
// The quirks of ==\n[] == 0; // true\n\"\" == 0; // true\nnull == undefined; // true\n\n// But...\n\"0\" == 0; // true\n\"0\" == []; // false (Wait, what?)The Three Levels of Comparison
1) Loose Equality (==)
Performs "Abstract Equality Comparison". It is unpredictable and generally considered a bad practice because it can lead to subtle bugs.
2) Strict Equality (===) - THE STANDARD
Performs "Strict Equality Comparison". No type conversion allowed. If types differ, it returns false. This is what you should use 99% of the time.
Exception: NaN === NaN is false, and 0 === -0 is true.
3) Same-Value Equality (Object.is)
The most precise comparison. It fixes the quirks of === and mirrors how memory handles these specific values.
Object.is(NaN, NaN); // true\nObject.is(0, -0); // false (Correctly identifies signed zero)Implementation (Interactive Demo)
This demo shows how Object.is behaves differently compared to === when dealing with edge cases like NaN.
\"use client\"\n\nimport { useState } from 'react';\n\nexport default function ComparisonDemo() {\n const [val1, setVal1] = useState(NaN);\n const [val2, setVal2] = useState(NaN);\n\n const isStrictEqual = val1 === val2;\n const isSameValue = Object.is(val1, val2);\n\n return (\n <div className=\"p-4 border rounded-lg bg-gray-50 flex flex-col gap-2\">\n <p>Comparing <code>NaN</code> and <code>NaN</code>:</p>\n <ul className=\"list-disc pl-5\">\n <li>Strict (===): <span className=\"text-red-500 font-bold\">{String(isStrictEqual)}</span></li>\n <li>Object.is: <span className=\"text-green-500 font-bold\">{String(isSameValue)}</span></li>\n </ul>\n </div>\n );\n}Summary & Best Practices
- Default to ===: Protects against unexpected type coercion.
- Use Object.is for Edge Cases: Essential for complex state management where NaN or -0 needs to be distinguished accurately.
- Delete == from your memory: Unless you have a specific reason to allow type coercion (even then, explicit conversion is better).
Conclusion
JavaScript's comparison rules can be confusing, but by following a "strict-first" approach, you can eliminate an entire class of subtle bugs. Object.is provides the ultimate precision when the standard operators fall short.