How Lodash _.eq Handles JavaScript Symbols

This article provides an overview of how the Lodash utility function _.eq evaluates the equivalence of two isolated Symbol instances that have matching descriptions. It examines the underlying comparison algorithm used by Lodash, explains the inherent identity characteristics of JavaScript symbols, and clarifies why _.eq treats structurally identical, isolated symbols as unequal.

The Comparison Mechanism of _.eq

In the Lodash library, _.eq is designed to perform a comparison based on the ECMAScript SameValueZero specification. Internally, the function is implemented essentially as follows:

function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

The SameValueZero check differs from strict equality (===) primarily in its handling of NaN, treating NaN === NaN as true. For all other primitive data types, including symbols, _.eq behaves identically to the JavaScript strict equality operator.

JavaScript Symbol Uniqueness

In JavaScript, a Symbol is a primitive data type where every call to Symbol() produces a globally unique token. Even when two symbols are instantiated with identical descriptions (for example, Symbol('key')), their internal identities remain distinct.

const symbolA = Symbol('identifier');
const symbolB = Symbol('identifier');

console.log(symbolA === symbolB); // false

The string passed to the Symbol() factory function is merely an optional, human-readable description for debugging purposes and does not establish structural identity.

Processing Isolated Symbols with _.eq

When _.eq processes two isolated Symbol instances, the comparison proceeds through standard identity checks:

  1. Lodash receives symbolA and symbolB.
  2. It evaluates symbolA === symbolB. Because the JavaScript runtime allocates unique memory references to each symbol primitive, this returns false.
  3. It performs the fallback NaN check (value !== value && other !== other), which also evaluates to false because symbols are not NaN.
  4. The function returns false.
const _ = require('lodash');

const first = Symbol('config');
const second = Symbol('config');

_.eq(first, second); // returns false

_.eq vs. Structural Equivalence

The _.eq method is a shallow comparison function and does not inspect internal properties, prototypes, or string descriptions of non-matching values. It does not attempt to parse symbolA.description === symbolB.description.

Even if you use Lodash's deep comparison method, _.isEqual, two distinct symbol primitives will still evaluate to false because JavaScript symbols are deliberately non-interchangeable primitives.

The only scenario where _.eq evaluates two symbols as equal is when both references point to the exact same symbol instance in memory, or when they point to the same registered symbol created via the global symbol registry:

// Referencing the same instance
const original = Symbol('data');
const reference = original;
_.eq(original, reference); // returns true

// Referencing the global symbol registry
const globalA = Symbol.for('shared');
const globalB = Symbol.for('shared');
_.eq(globalA, globalB); // returns true

For isolated symbols created via Symbol(), structural equivalence is intentionally ignored by _.eq in strict adherence to ECMAScript primitive identity rules.