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:

  1. If both values are of different types, they are not equal (false).
  2. If both values are primitives of the same type and have the same value, they are equal (true).
  3. If both values are objects, functions, or arrays, they are only equal if they share the exact same reference in memory (true).
  4. Two NaN values are considered equal (true).
  5. +0 and -0 are 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; // false

In contrast, _.eq considers two NaN values equal:

_.eq(NaN, NaN); // true

For all other primitive values, _.eq behaves identically to ===:

_.eq('hello', 'hello'); // true
_.eq('42', 42);         // false (types differ)
_.eq(null, undefined);  // false

How _.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:

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:

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