How Lodash _.eq Performs Strict Equality Checks
The _.eq method in Lodash evaluates two values to
determine if they are equivalent using a specialized strict equality
check. While it functions similarly to native JavaScript comparison
mechanisms, it addresses specific edge cases that standard operators
overlook. This article explains how _.eq operates behind
the scenes, how it utilizes the ECMAScript SameValueZero specification,
and how it differs from the === operator and other
comparison utilities.
The Core Mechanism: SameValueZero
At its core, Lodash's _.eq implements the ECMAScript
SameValueZero comparison algorithm. This determines
equality based on the following rules:
- If both values are of different types, they are not equal
(
false). - If both values are primitives of the same type and have the same
value, they are equal (
true). - If both values are objects, functions, or arrays, they are only
equal if they share the exact same reference in memory
(
true). - Two
NaNvalues are considered equal (true). +0and-0are considered equal (true).
How _.eq Differs from
===
The standard JavaScript strict equality operator (===)
adheres to the IsStrictlyEqual algorithm, which contains a well-known
quirk involving NaN:
NaN === NaN; // falseIn contrast, _.eq considers two NaN values
equal:
_.eq(NaN, NaN); // trueFor all other primitive values, _.eq behaves identically
to ===:
_.eq('hello', 'hello'); // true
_.eq('42', 42); // false (types differ)
_.eq(null, undefined); // falseHow _.eq Differs
from Object.is
JavaScript also provides Object.is, which implements the
SameValue algorithm. While both Object.is
and _.eq treat NaN as equal to
NaN, they handle signed zeros differently:
Object.is(SameValue): Distinguishes between positive zero and negative zero.Object.is(+0, -0); // false_.eq(SameValueZero): Treats positive zero and negative zero as equal._.eq(+0, -0); // true
In most software applications, distinguishing between +0
and -0 is unnecessary and can cause unintended comparison
failures. By using SameValueZero, _.eq provides an
intuitive equality check that aligns with standard data-handling
expectations.
Reference Types and Deep Equality
It is critical to distinguish _.eq from deep equality
checks:
_.eqtests referential identity for non-primitive types. Two distinct objects with identical properties will returnfalse.const objA = { id: 1 }; const objB = { id: 1 }; _.eq(objA, objB); // false _.eq(objA, objA); // true
For recursive, structural comparisons of objects and arrays, Lodash
provides _.isEqual instead.
Summary of Differences
| Comparison | === |
Object.is |
_.eq |
|---|---|---|---|
'a' === 'a' |
true |
true |
true |
NaN vs NaN |
false |
true |
true |
+0 vs -0 |
true |
false |
true |
{} vs {} |
false |
false |
false |