Use object as a key in map or set in JavaScript
This post will discuss how to use an object as a key in map or set in JavaScript.
Using an object as a key in a map or set in JavaScript is a possible but not very common task. A map is a collection of key-value pairs, where each key can have only one associated value. A set is a collection of unique values, where each value can only appear once. Both map and set allow keys or values of any type, including objects. However, there are some caveats and limitations to be aware of when using objects as keys in map or set.
One of the main challenges is that objects are compared by reference, not by value. This means that two objects with the same properties and values are not considered equal, unless they refer to the same object in memory. The following code illustrates this:
|
1 2 3 4 5 6 7 8 9 |
// Create two objects with the same properties and values let obj1 = {name: "Emma"}; let obj2 = {name: "Emma"}; // Compare them by reference console.log(obj1 === obj2); // false // Compare them by value console.log(JSON.stringify(obj1) === JSON.stringify(obj2)); // true |
This has implications for using objects as keys in map or set. If we use different objects with the same properties and values as keys in a map, they will be treated as distinct keys, and each will have its own associated value. Similarly, if we use different objects with the same properties and values as values in a set, they will be treated as distinct values, and each will be added to the set. The following code illustrates this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// Create a map let map = new Map(); // Use different objects with the same properties and values as keys map.set({name: "Emma"}, "value1"); map.set({name: "Emma"}, "value2"); // Check the size and contents of the map console.log(map.size); // 2 console.log(map.get({name: "Emma"})); // undefined // Create a set let set = new Set(); // Use different objects with the same properties and values as values set.add({name: "Emma"}); set.add({name: "Emma"}); // Check the size and contents of the set console.log(set.size); // 2 console.log(set.has({name: "Emma"})); // false |
As we can see, the map and set do not recognize the objects as equal, and do not return the expected results. This is because each time we create a new object literal, such as {name: "Emma"}, it is a different object in memory, even if it has the same properties and values as another object.
1. Using object itself as the key
To avoid this problem, we need to use the same object reference as the key in map or value in set. This way, the map and set can identify the object correctly and return the expected results. This is the simplest and most straightforward way, but it requires us to keep a reference to the object in order to access its value in the map or set. The following code illustrates this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Create an object let obj = {name: "Emma"}; // Create a map let map = new Map(); // Use the same object reference as the key map.set(obj, "value1"); map.set(obj, "value2"); // Check the size and contents of the map console.log(map.size); // 1 console.log(map.get(obj)); // value2 // Create a set let set = new Set(); // Use the same object reference as the value set.add(obj); set.add(obj); // Check the size and contents of the set console.log(set.size); // 1 console.log(set.has(obj)); // true |
Note that objects are not easily searchable or sortable by their properties or values. This means that to find or order the keys or values in a map or set based on some criteria, we need to use additional functions or techniques to do so. For example, to find all keys in a map that have a certain property or value, we need to use a loop or an iterator to check each key individually. Similarly, to sort the keys or values in a map or set by some criteria, we need to convert them into an array and use a custom compare function to do so.
2. Using a hash function
Another option is to use a hash function to convert each object into a string as the key. This function involves applying a hash function to each object, and using the resulting string as the key in the map or set. We can create a custom function that generates a unique string based on the properties and values of the object. For example, we can use something like this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// Create a custom hash function function hashFunction(obj) { // Initialize an empty array let arr = []; // Loop through the object's own properties for (let key in obj) { // Check if the property is enumerable if (obj.hasOwnProperty(key)) { // Push the property name and value into the array arr.push(key + ':' + obj[key]); } } // Sort the array alphabetically arr.sort(); // Join the array elements with a separator and return it return arr.join('|'); } // Create a map let map = new Map(); // Use different objects with the same properties and values as keys // Convert the object into a string first using hashFunction map.set(hashFunction({name: "Emma"}), "value1"); map.set(hashFunction({name: "Emma"}), "value2"); // Check the size and contents of the map console.log(map.size); // 1 console.log(map.get(hashFunction({name: "Emma"}))); // value2 console.log(map.has(hashFunction({name: "Emma"}))); // true |
This method works well if we need to use arbitrary objects as keys, and we care about their actual content. However, it requires us to choose a hash function that can handle all possible objects, and that produces unique strings for different objects. Otherwise, we may encounter collisions or inconsistencies in our map or set. Also, us to write and maintain our own hash function, which can be complex and time-consuming.
That’s all about using an object as a key in map or set in JavaScript.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)