EquivalentKeyMap
is a variant of a Map
object which enables lookup by equivalent (deeply equal) object and array keys.
With a standard Map
, a value is only returned if its key is strictly equal to the one used in assigning its value.
const map = new Map();
map.set( { a: 1 }, 10 );
map.get( { a: 1 } );
// ⇒ undefined
By contrast, EquivalentKeyMap
considers key equality of objects and arrays deeply:
const map = new EquivalentKeyMap();
map.set( { a: 1 }, 10 );
map.get( { a: 1 } );
// ⇒ 10
EquivalentKeyMap is published as an npm package:
npm install equivalent-key-map
Browser-ready versions are available from unpkg. The browser-ready version assigns itself on the global scope as EquivalentKeyMap
.
<script src="https://unpkg.com/equivalent-key-map/dist/equivalent-key-map.min.js"></script>
<script>
var map = new EquivalentKeyMap();
// ...
</script>
EquivalentKeyMap
is intended to recreate the same API properties and methods available for Map
:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
Note: Currently, only methods and properties supported by IE11 are implemented (see Browser compatibility).
There is inevitably some overhead in tracking object and array references deeply, contrasted with the standard Map object. This is a compromise you should consider when deciding whether you need deep key equality behavior.
That said, EquivalentKeyMap
was implemented with performance in mind, and is significantly faster — and importantaly, more correct — than a number of alternative naive approaches. It also optimizes for repeated calls with the same object reference, memoizing the latest invocation of get
to shortcut lookups.
The following benchmark results describe the behavior of EquivalentMap#get
with keys of varying property lengths.
EquivalentKeyMap (2 properties, equal reference) x 38,726,559 ops/sec ±1.25% (87 runs sampled)
EquivalentKeyMap (8 properties, equal reference) x 43,395,727 ops/sec ±0.64% (91 runs sampled)
EquivalentKeyMap (18 properties, equal reference) x 51,334,445 ops/sec ±0.54% (87 runs sampled)
EquivalentKeyMap (2 properties) x 2,419,300 ops/sec ±1.37% (85 runs sampled)
EquivalentKeyMap (8 properties) x 1,362,012 ops/sec ±0.40% (90 runs sampled)
EquivalentKeyMap (18 properties) x 569,431 ops/sec ±0.93% (88 runs sampled)
JSONStringifyNaiveMap (2 properties) x 1,958,910 ops/sec ±0.33% (94 runs sampled)
JSONStringifyNaiveMap (8 properties) x 1,038,380 ops/sec ±0.34% (94 runs sampled)
JSONStringifyNaiveMap (18 properties) x 600,017 ops/sec ±0.39% (91 runs sampled)
JSONStringifyOptimizedMap (2 properties) x 2,143,323 ops/sec ±0.36% (94 runs sampled)
JSONStringifyOptimizedMap (8 properties) x 1,088,846 ops/sec ±0.51% (92 runs sampled)
JSONStringifyOptimizedMap (18 properties) x 627,801 ops/sec ±0.31% (91 runs sampled)
JSONStableStringifyMap (2 properties) x 279,919 ops/sec ±0.91% (85 runs sampled)
JSONStableStringifyMap (8 properties) x 129,635 ops/sec ±0.55% (93 runs sampled)
JSONStableStringifyMap (18 properties) x 64,372 ops/sec ±0.40% (94 runs sampled)
FasterStableStringifyMap (2 properties) x 383,185 ops/sec ±0.79% (85 runs sampled)
FasterStableStringifyMap (8 properties) x 174,948 ops/sec ±0.48% (88 runs sampled)
FasterStableStringifyMap (18 properties) x 89,142 ops/sec ±0.46% (94 runs sampled)
TupleStringifyMap (2 properties) x 885,499 ops/sec ±0.50% (92 runs sampled)
TupleStringifyMap (8 properties) x 404,241 ops/sec ±0.56% (90 runs sampled)
TupleStringifyMap (18 properties) x 206,659 ops/sec ±0.74% (93 runs sampled)
StableQuerystringMap (2 properties) x 920,191 ops/sec ±0.72% (86 runs sampled)
StableQuerystringMap (8 properties) x 343,097 ops/sec ±0.40% (92 runs sampled)
StableQuerystringMap (18 properties) x 157,483 ops/sec ±0.50% (93 runs sampled)
You can run these on your own machine by cloning the repository, installing dependencies, and running npm run benchmark
.
git clone https://github.com/aduth/equivalent-key-map.git
cd equivalent-key-map
npm install
npm run benchmark
EquivalentKeyMap
is implemented using Map
and follows the corresponding browser compatibility. Notably, this includes all modern browsers and Internet Explorer 11. The Map
methods not supported by Internet Explorer 11 are not used by EquivalentKeyMap
and can be safely overlooked.
If you need support for older browsers, it's recommended that you use a polyfill such as core-js
.
Copyright 2018 Andrew Duthie
Released under the MIT License.