An open API service indexing awesome lists of open source software.

https://github.com/aduth/equivalent-key-map

A Map variant which allows for equivalent (deeply equal) object and array keys
https://github.com/aduth/equivalent-key-map

Last synced: 3 months ago
JSON representation

A Map variant which allows for equivalent (deeply equal) object and array keys

Awesome Lists containing this project

README

          

# EquivalentKeyMap

`EquivalentKeyMap` is a variant of a [`Map` object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) which enables lookup by _equivalent_ (deeply equal) object and array keys.

## Example

With a standard `Map`, a value is only returned if its key is strictly equal to the one used in assigning its value.

```js
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:

```js
const map = new EquivalentKeyMap();
map.set( { a: 1 }, 10 );
map.get( { a: 1 } );
// ⇒ 10
```

## Installation

EquivalentKeyMap is published as an [npm](https://www.npmjs.com/) package:

```
npm install equivalent-key-map
```

Browser-ready versions are available from [unpkg](https://unpkg.com/equivalent-key-map/dist/equivalent-key-map.min.js). The browser-ready version assigns itself on the global scope as `EquivalentKeyMap`.

```html

var map = new EquivalentKeyMap();

// ...

```

## Usage

`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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Browser_compatibility)).

## Performance Considerations

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](https://github.com/aduth/equivalent-key-map/blob/210f42bbd431c7c10da33d310cf56ef3b3ca96e7/test/index.js#L67-L71) — than a number of [alternative naive approaches](https://github.com/aduth/equivalent-key-map/tree/master/benchmark/impl). It also optimizes for repeated calls with the same object reference, memoizing the latest invocation of `get` to shortcut lookups.

### Benchmarks

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
```

## Browser Support

`EquivalentKeyMap` is implemented using `Map` and follows the corresponding [browser compatibility](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#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`](https://github.com/zloirock/core-js).

## License

Copyright 2018 Andrew Duthie

Released under the [MIT License](https://github.com/aduth/equivalent-key-map/tree/master/LICENSE.md).