What is the equivalent of a hashmap in JavaScript? As noted in an update on a related answer, using the notation:
var hash = {};
hash[X]
The above does not truly hash the object X; instead, it converts X to a string (using .toString() for objects or other built-in conversions for different primitive types) and then looks up that string in “hash.” This means that object equality isn’t considered—if two different objects have the same string representation, they will overwrite each other.
Given this context, are there any efficient implementations of a hashmap in JavaScript that address these issues?
For reference, many results I found on JavaScript hashmaps indicate that some implementations have O(n) complexity for any operation, while others overlook the fact that different objects with equivalent string representations can overwrite each other.
The native Map object in JavaScript provides an efficient way to implement a hashmap.
It allows you to use objects as keys without converting them to strings, thus maintaining their reference.
// Create a new Map
const myMap = new Map();
// Set key-value pairs
const key1 = { id: 1 };
const key2 = { id: 2 };
myMap.set(key1, 'Value for object 1');
myMap.set(key2, 'Value for object 2');
// Retrieve values
console.log(myMap.get(key1)); // 'Value for object 1'
console.log(myMap.get(key2)); // 'Value for object 2'
You can create a custom hashmap that utilizes an internal array to manage key-value pairs while checking for object equality:
class HashMap {
constructor() {
this.map = [];
}
// Method to add or update a key-value pair
set(key, value) {
// Check if the key already exists
for (let i = 0; i < this.map.length; i++) {
if (this.map[i][0] === key) {
this.map[i][1] = value; // Update value
return;
}
}
this.map.push([key, value]); // Add new key-value pair
}
// Method to retrieve a value by key
get(key) {
for (let i = 0; i < this.map.length; i++) {
if (this.map[i][0] === key) {
return this.map[i][1]; // Return value
}
}
return undefined; // Key not found
}
}
// Usage
const myHashMap = new HashMap();
const obj1 = { name: 'Alice' };
myHashMap.set(obj1, 'User 1');
console.log(myHashMap.get(obj1)); // 'User 1'
If you want to ensure that the keys are objects and they are garbage collected when no longer in use, consider using WeakMap. This way, the memory is managed efficiently.
// Create a new WeakMap
const myWeakMap = new WeakMap();
// Set key-value pairs with object keys
const objKey = { id: 1 };
myWeakMap.set(objKey, 'Value for object key');
// Retrieve values
console.log(myWeakMap.get(objKey)); // 'Value for object key'
// Note: You cannot list all keys in WeakMap, as it's not enumerable