A HashMap for the modern Javascript world ⚡
npm install objectmap.js
// Compares keys by *data*, not by object identity
const friendCounts = new ObjectMap<{ name: string }, number>();
friendCounts.set({ name: "Foo" }, 4);
friendCounts.set({ name: "Bar" }, 6)
// In ES2015's Map, this returns false
console.log(friendCounts.has({ name: "Foo" })) // true
// In ES2015's Map, these return undefined
console.log(friendCounts.get({ name: "Foo" })) // 4
console.log(friendCounts.get({ name: "Bar" })) // 6
// Compliant with ES2015's Map API
console.log([...friendCounts.keys()]) // [{ name: "Foo" }, { name: "Bar" }]
console.log(friendCounts.delete({ name: "Foo" })) // true
// ... but has a lot more to offer:
// filter(), map(), reduce(), sort(), some(), every(),
// update(), pop(), clone(), etc.
// Features a `Set` implementation, too
const friends = new ObjectSet<{ name: string }>();
friends.add({ name: "Foo" });
// In ES2015's Set, this returns `false`
console.log(friends.has({ name: "Foo" })) // `true`
// And immutable versions, too
const map = new ImmutableMap()
const set = new ImmutableSet()
- 💡 Compare keys by value, not by reference: Referential equality is outdated - JavaScript objects are nowadays compared by the information they engrain.
objectmap.js
's crown feature is hashing and comparing objects by value rather than their place in memory; you'll find thatObjectMap
andObjectSet
are a natural fit where the nativeMap
andSet
should have been (read more below). - 🧰 Equipped with utilities: alongside the standard
Map
andSet
interfaces,objectmap.js
provides convenient methods for dealing with collections (e.g. filter(), map(), reduce(), sort()), factories (e.g. fromSet(), keysOf()) and others (e.g. pop(), update()). - 💯 Has all the numbers:
objectmap.js
is fast, small, well tested, side effect free, and is written in TypeScript.
In the modern JavaScript world, an object is almost always determined solely by information that it contains - two objects with the same keys and values are considered equal, for virtually all intents and purposes.
This is not surprising, given some of the common actions modern applications perform on data: they transfer it between services, serialize & deserialize it, and mutate it in a functional flavor (i.e. creating new objects rather than changing the existing onces).
Together with the increasingly large scale of apps, referential equality - that is, declaring that two objects are equal only if they are the very same instance, stored in the same place in memory - is obsolete.
However, JavaScript has no standard way of checking equality of two objects by their data. When dealing with objects directly, you can use an npm package (e.g. fast-deep-equal), but more complex structures such as Map
s and Set
s still rely on referential identity (and can't be effectively overriden), making them useless in many situations where they would otherwise be a great fit.
objectmap.js
was created with this problem exactly in mind - instead of using a kludge to turn objects into primitive values and using those as a map keys, or inefficiently using an array, you can work with complex objects and arrays as keys.
objectmap.js
exposes four classes - ObjectMap
, ObjectSet
, ImmutableMap
and ImmutableSet
- as well as some types and utilities.
A HashMap implementation. By default, compares keys by value (deep equality), rather than Object.is
or similar referential equality.
Compliant with ES6's Map interface.
The generic parameters K
and V
correspond to the key and value type, respectively;
often they can be inferred from the context (especially if an iterable
is passed), but might night to be supplied explicitly.
Parameters:
iterable
: an iterable of key-value pairs, used to initialize the map.
If this is anObjectMap
, this constructor will create a copy. Otherwise, if the iterable has alength
orsize
property - its value will be used as the initial capacity (can be overriden byinitialCapacity
inoptions
).options
: constructor options; see ObjectMapOptions.
To initialize a map without an iterable but with custom options, pass undefined
as the iterable - new ObjectMap(undefined, { /* options */ })
.
Returns the number of key-value pairs in the map.
Returns true
if the map is empty (of size 0
), and false
otherwise.
Adds a new element with a specified key and value to the map. If an element with the same key already exists, the element will be updated.
Returns the map object (this
), for chaining.
Parameters:
key
: the key to use.value
: the value to associate with the key.
Returns the value associated with the specified key. If no value is associated with the specified key, undefined
is returned.
Parameters:
key
: the key to search for.
Removes a key-value pair from the map.
Returns true
if the pair existed and was removed, or false
if the key does not exist.
Parameters:
key
: the key to search for.
Returns true
if the map has a value associated with the given key
, and false
otherwise.
Parameters:
key
: the key to search for.
Removes all key-value pairs from the map.
Returns an iterable of keys in the map.
Returns an iterable of values in the map.
Returns an iterable of key, value pairs for every entry in the map.
Executes a provided function once per each key/value pair in the map, in insertion order.
Parameters:
callbackfn
: the callback to execute for each pair.thisArg
: optional argument to use as the value ofthis
.
Creates a clone of the map; does not create a deep copy keys or values.
map.clone()
is equivalent to new ObjectMap(map)
.
Returns a map with the same options as this
, but no keys or values.
Returns a new map containing only the key-value pairs that satisfy the predicate. Retains the same options as the original map.
Parameters:
predicate
: the function called to test which pairs to keep. Called once for each key-value pair.
Returns a new map with the same keys, and the results of calling transform
for each key-value pair as values.
Parameters:
transform
: the function called to transform the map's values. Called once for each key-value pair.
Calls reducer
for each key-value pair, accumulating the results into a single value.
Parameters:
reducer
: the function to reduce by. Called once for each key-value pair.
Returns true
if the map contains a key-value pair that satisfies the predicate, and false
otherwise.
Parameters:
predicate
: the predicate called to test key-value pairs by.
Returns true
if every key-value pair in the map satisfies the predicate, and false
otherwise.
Parameters:
predicate
: the predicate called to test key-value pairs by.
Sorts the map in-place using the provided compare function. uses Array.prototype.sort
under the hood.
Parameters:
compareFn
: comparator function; passed toArray.prototype.sort
.
returns true
if this map and the other map are equal, and false
otherwise; equality here is defined as having the same key sets, and the same values for each key. Equality is tested using the equals
function provided in the constructor options.
Parameters:
other
: the map to test equality against
Removes the value associated with the given key, and returns it. This is like delete()
, except the value
(or undefined
) is returned.
If the key is not in the map, returns undefined
.
Parameters:
key
: the key to search for.
Updates the value associated with the given key, using the updater
function. Note that if the key is not in the map, updater will be called with undefined
.
Parameters:
key
: the key to search for.updater
: the transformer to call for the associated value.
Returns the number of buckets in the map, mostly intended for internal purposes.
The current options used by the map, mostly intended for internal purposes. Note, this is a getter - changing this does not actually change the map's options.
static fromSet<K, V>(set: SetLike<K>, factory: (key: K) => V, options?: ObjectMapOptions): ObjectMap<K, V>
Static factory for creating a map from a set-like object and a function.
Parameters:
set
: a set-like object to get the map's keys fromfactory
: called for each key, the result is used as the new map's value.options
: optional constructor options.
ImmutableMap
is the immutable variant of ObjectMap
, all mutating methods return a new ImmutableMap
with the changes applied rather than mutating the current instance.
That means ImmutableMap
's API is the same as ObjectMap
's API except for the following differences:
Returns a new map with the given value
associated with the given key
(whether the value is updated from an old one or added).
Returns a new map with the given key removed, if it was present.
Returns an empty clone of this map.
Returns a new map with the same keys, sorted by the given function.
Returns a new map with the value for the given key updated to the result of updater
.
A Set implementation. By default, compares keys by value (deep equality), rather than Object.is
or similar referential equality.
Compliant with ES6's Set interface.
The generic parameter T
marks the set member type; it can often be inferred from the context (especially if an iterable
is passed), but might night to be supplied explicitly.
Parameters:
iterable
: an iterable, used to initialize the map.
If this is anObjectSet
, this constructor will create a copy. Otherwise, if the iterable has alength
orsize
property - its value will be used as the initial capacity (can be overriden byinitialCapacity
inoptions
).options
: constructor options; see ObjectMapOptions.
Returns the number of members in the set.
Returns true
if the set is empty (of size 0
), and false
otherwise.
Appends the given value to the set; if it's already present, nothing is changed.
Parameters:
value
: the value to add.
Returns true
if the value is a member of the set, and false
otherwise.
Parameters:
value
: the value to search for.
Removes the given value from the set.
Returns true
if value was a member and was removed, or false
if the key does not exist.
Parameters:
value
: the value to delete.
Removes all members from the set.
Iterates all members of the set, in insertion order.
Iterates all members of the set, in insertion order.
Yields an iterable of [v,v]
pairs for every value v in the set.
Executes a provided function once per each member in the set, in insertion order.
Parameters:
callbackfn
: the callback to execute for each member.thisArg
: optional argument to use as the value ofthis
.
Creates a clone of the set; does not create a deep copy of the members.
set.clone()
is equivalent to new ObjectSet(set)
.
Returns a new set with the same options as this but no keys or values.
Returns a new set containing only the members that satisfy the predicate. Retains the same options as the original set.
Parameters:
predicate
: the function called to test which members to keep. Called once for each member.
Returns a new set containing the results of calling transform
on each member.
Parameters:
transform
: the function called to transform the set's values. Called once for each key-value pair.
Calls reducer
for each member, accumulating the results into a single value.
Parameters:
reducer
: the function to reduce by. Called once for each member.
Returns true
if the set contains a member that satisfies the predicate, and false
otherwise.
Parameters:
predicate
: the predicate to test members by.
Returns true
if every member in the set satisfies the predicate,
and false
otherwise.
Parameters:
predicate
: the predicate to test members by.
Sorts the set in-place using the provided compare function. uses Array.prototype.sort
under the hood.
Parameters:
compareFn
: comparator function; passed toArray.prototype.sort
.
Returns true
if this set and the other set are equal; equality here is defined as having exactly the same members. Equality of members is tested using the equals
function provided in the constructor options.
Parameters:
other
: the set to test equality against.
Returns a new set containing exactly the members that are both in this set and in other
.
Parameters:
other
: the set-like object to intersect with.
Returns a new set containing exactly the members that are either in this set, in other
or both.
Parameters:
other
: the set-like object to take the union with.
Returns a new set containing exactly the members that are in this set but not in other
.
Parameters:
other
: the set-like object to diff from this set.
Returns a new set containing exactly the members that are in this set or in other
, but not in both.
Parameters:
other
: the set-like object to take the symmetric difference with respect to.
Returns true
if every element in this set is also in other
, and false
otherwise.
Parameters:
other
: the set-like object to check against.
Returns true
if this set contains every element in other
, and false
otherwise.
Parameters:
other
: the set-like object to check against.
Returns true
if this set and other
have no members in common, and false
otherwise.
Parameters:
other
: the set-like object to check against.
Creates an ObjectSet
from the keys of a Map
(possibly an ObjectMap
) or an object.
Parameters:
obj
: the map or object to take the keys of.
Creates an ObjectSet
from the values of a Map
(possibly an ObjectMap
) or an object.
Parameters:
obj
: the map or object to take the values of.
ImmutableSet
is the immutable variant of ObjectSet
, all mutating methods return a new ImmutableSet
with the changes applied rather than mutating the current instance.
That means ImmutableSet
's API is the same as ObjectSet
's API except for the following differences:
Returns a new set with the given value added as a member.
Returns a new set with the given value excluded.
Returns an empty clone of this set.
Returns a new set with the same members, sorted by the given function.
Constructor options for the ObjectMap
, ObjectSet
, ImmutableMap
and ImmutableSet
classes.
The initial capacity of the map; defaults to 32
.
For a map with constant capacity, set this together with loadFactor=1
The threshold above which the map will resize; defaults to 0.75
.
For a map that never resizes, set this to 1
.
The function used to compare keys for equality; defaults to a deep equality function (exported as equals
).
The function used to hash keys; defaults to a deep hash function (exported as hash
).
A set-like object, as per the mozilla docs