Equality as values
Immutable.js collections are treated as pure data values. Two immutable
collections are considered value equal (via .equals() or
is()) if they represent the same collection of values. This
differs from JavaScript's typical reference equal (via === or ==) for
Objects and Arrays, which only determines if two variables represent references
to the same object instance.
Consider the example below, where two identical Map instances are not
reference equal but are value equal.
// First consider:
const obj1 = { a: 1, b: 2, c: 3 };
const obj2 = { a: 1, b: 2, c: 3 };
obj1 !== obj2; // two different instances are always not equal with ===
Value equality allows Immutable.js collections to be used as keys in Maps or values in Sets, and retrieved with different but equivalent collections:
Note: is() uses the same measure of equality as Object.is for scalar strings and numbers, but uses value equality for Immutable collections, determining if both are immutable and all keys and values are equal using the same measure of equality.
Performance tradeoffs
While value equality is useful in many circumstances, it has different performance characteristics than reference equality. Understanding these tradeoffs may help you decide which to use in each case, especially when used to memoize some operation.
When comparing two collections, value equality may require considering every
item in each collection, on an O(N) time complexity. For large collections of
values, this could become a costly operation. Though if the two are not equal
and hardly similar, the inequality is determined very quickly.
In contrast, when comparing two collections with reference equality, only the
initial references to memory need to be compared, which is not based on the size
of the collections and has an O(1) time complexity. Checking reference equality
is always very fast, however just because two collections are not
reference-equal does not rule out the possibility that they may be value-equal.
Return self on no-op
When possible, Immutable.js avoids creating new objects for updates where no change in value occurred, to allow for efficient reference equality checking to quickly determine if no change occurred.
This is extremely useful within a memoization function which would prefer to
re-run the function rather than pay for a deeper equality check. The === check
is also used internally by is() and .equals() as a performance optimization.
However, updates which do result in a change will return a new reference. Each of these operations occurs independently, so two similar updates will not return the same reference: