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); // falseThe 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:
- Lodash receives
symbolAandsymbolB. - It evaluates
symbolA === symbolB. Because the JavaScript runtime allocates unique memory references to each symbol primitive, this returnsfalse. - It performs the fallback
NaNcheck (value !== value && other !== other), which also evaluates tofalsebecause symbols are notNaN. - 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 trueFor isolated symbols created via Symbol(), structural
equivalence is intentionally ignored by _.eq in strict
adherence to ECMAScript primitive identity rules.