Sets & Maps in JavaScript

When it comes to picking the right data structure, developers often invest significant time in choosing what should be implemented. A good data structure can simplify data operations, save time, and make code more comprehensive.

Collections of data are commonly stored using Objects and Arrays. For storing keys/value pairs, developers use Objects, and for storing indexed lists, they use Arrays.

Iterable objects in ECMAScript 2015 presented two new types: Maps and Sets in JavaScript. These are "keyed collections", which implies that their behavior differs slightly and proffers better performance.

The term "keyed collections" refers to data collections that are ordered according to a key rather than an index. A key characteristic of them is that they are associative. Sets and maps are keyed collections that are iterable in order of insertion.

There were limitations to JavaScript's collections in the past. Arrays are the only data structure that JavaScript provides, whereas other languages have lists, sets, associative maps, and dictionaries.

In JavaScript, it was necessary to come up with workarounds to create sets or maps, which made it difficult to maintain the code. The new JavaScript ES6 standard comes with new built-in maps and sets in JavaScript that simplify the process of programming.

Table Of Contents

What are Maps in JavaScript?

A map object is a collection of key-value pairs, where each element is held as a unique key-value pair.  By iterating through a Map object by key-value pairs implying a for...of the loop, which returns a 2-member array of [key, value] for each iteration.

As map collection JavaScript return their key-value pairs in the same order as they were entered when iterated over.

The JavaScript development community used objects for a long time to map keys to values before ES6 was oriented. A map can, however, be created from an object, but it has its constraints. As an example:

  • It is not possible to iterate over keys reliably, and the keys() method converts fields to strings, causing keys to collide.
  • A simple method for adding new keys and values does not exist.
Maps
Maps

With ES6, a number of improved integrated classes were introduced, most notably a collection type called Map, capable of holding key-value pairs of any type. With the new Map object, key insertion order can be determined, which is in contrast to the old object technique.

An associative collection of keys and values is what characterizes a JavaScript Map. Any primitive or object can be used as a key or a value. Many valuable uses can be derived from this data structure. Whenever we iterate over the map object, the key, and value pair return in the same order as when it was initialized.

The syntax for initiating a new Map is as follows:

let map = new Map()

As a result, we have an empty map:

Output

Map(0) {}

Overview of Maps' keys, values, and entries

By utilizing the attributes of the Object constructor, objects can fetch keys, values, and entries. Alternatively, Maps expose prototype methods that let us get the keys, values, and entries instantly from the Map instance.

Arrays and MapIterators work the same way, with for...of to loop through the values returned by keys(), values(), and entries(). For exhibiting these methods, here is another instance of a Map:

let monitoringTools = new Map([
    ["apm", "application performance monitoring"],
    ["rum", "real user monitoring"],
    ["infra", "infrastructure monitoring"]
]);

console.log(monitoringTools);
Output:

Map (3) {"apm" => "application performance monitoring", "rum" => "real user monitoring", "infra" => "infrastructure monitoring"} 

Using the keys() method, you can retrieve the keys as follows:

monitoringTools.keys()
Output

[Map Iterator] { 'apm', 'rum', 'infra' }

Values are returned by the values() method as follows:

monitoringTools.values()
Output

[Map Iterator] {
  'application performance monitoring',
  'real user monitoring',
  'infrastructure monitoring' }

A key/value pair array is returned by the entries() method:

monitoringTools.entries()
Output:

[Map Iterator] {
  [ 'apm', 'application performance monitoring' ],
  [ 'rum', 'real user monitoring' ],
  [ 'infra', 'infrastructure monitoring' ] }

Complete Example:

let monitoringTools = new Map([
    ["apm", "application performance monitoring"],
    ["rum", "real user monitoring"],
    ["infra", "infrastructure monitoring"]
    ]);

console.log(monitoringTools)

let keys = monitoringTools.keys();
console.log(keys);

let values = monitoringTools.values();
console.log(values);

let entries = monitoringTools.entries();
console.log(entries);

Output:

Map in JavaScript
Map in JavaScript

Iteration with Map

The Map function in JavaScript provides an efficient way to iterate through data using two different methods:

  1. forEach()
  2. for..of

1. forEach() in Maps

Maps have built-in forEach methods, similar to arrays, that allow them to iterate. Although they iterate over identical data, there are some subtle distinctions. While the Map forEach iterates through values, keys, and the map itself, the Array version iterates through item, index, and array.

// Map 
Map.prototype.forEach((value, key, map) = () => {})

// Array
Array.prototype.forEach((item, index, array) = () => {})

It is a huge asset for Maps over Objects since Objects must be converted using keys(), values(), or entries(), and there is no practical way to obtain properties without converting them.

The following code shows how to iterate through our Map and log the key/value pairs:

// Log the keys and values of the Map with forEach

monitoringTools.forEach((value, key) => {
  console.log(`${key}: ${value}`)
})
Output:

apm: application performance monitoring
rum: real user monitoring
infra: infrastructure monitoring

2. for..of in Maps

for..of is an essential loop structure which makes it easy to iterate through map objects and perform operations on the key-value pairs.

The same result achieved by destructuring the array of Map items, since a for...of loop iterates over iterables like Map and Array:

// Destructure the key and value out of the Map item
for (const [key, value] of monitoringTools) {
    console.log(`${key}: ${value}`)
}
Output:

apm: application performance monitoring
rum: real user monitoring
infra: infrastructure monitoring

Methods and properties of Maps

To serve as a reference, here is a table that enumerates Map properties and methods:

Properties/Methods

Description

Returns

set(key, value)

Affixes a key/value pair to a Map

Map Object

delete(key)

Eliminates a key/value pair from a Map by key

Boolean

get(key)

Gets the value by a key

value

has(key)

This method checks a Map by key for the inclusion of an element

Boolean

clear()

All items are removed from a map

N/A

keys()

This function returns all keys from a Map

MapIterator object

values()

Gets all values from a Map

MapIterator object

entries()

Map keys and values are returned as [key, value]

MapIterator object

forEach()

Iterates through the Map in insertion order

N/A

size

Returns the number of items in a Map

Number

Map Function Implementation

Here is an example of map() implementation:

let products = ["Application", "Real user", "Infra"];

let product = products.map(function(product) {
    return product + " Monitoring Tool";
});

console.log(product);
Output:

[ 'Application Monitoring Tool',
  'Real user Monitoring Tool',
  'Infra Monitoring Tool' ]

Application of Maps

The greatest benefit of Maps over objects is that they are equivalent to Objects in that they hold key-value pairs, but they also offer a few other advantages; Accordingly, Maps are among the most robust data structures.:

  • Size - Maps have a size property, but objects don't have an explicit method to specify their size.
  • Iteration - Maps can be iterated immediately, but Objects cannot.
  • Flexibility - Maps entitle any data type to be applied as the key to a value, while Objects can only utilize strings for keys.
  • Ordered - Objects do not have any certified order, but maps enclose their insertion order.

What are Sets in JavaScript?

A set is a multitude of items where no element can be recounted. JavaScript set in data structure can hold any kind of value, whether primitive or object. A set object is incapable to retain duplicate values. A set object iterates through its elements in the order they were initially created.

A set is a data structure that stores distinct objects in no particular order. Sets allow you to store multiple objects of the same type and compare them by their contents, as opposed to their position in an array or list.

Sets
Sets

A JavaScript set in data structure is a unique collection of primitives and objects, and duplicates are not allowed. A set is a data structure that stores unique values. It can store any type of object, including numbers, strings, or other sets. The values in a set are unordered and cannot be changed once they are added to the set.

The following code creates a new empty set:

const set = new Set()

As a result, we have an empty set:

Output:

Set(0) {}

Set's keys, values, and entries

Iterators can be returned by keys(), values(), and entries() methods of both Maps and Sets. All these methods have a typical function when it pertains to Maps, but Sets do not have keys, so they are assigned as substitutes for values instead.

In other words, both keys() and values() will return a similar Iterator, while entries() will return the exact value twice. Set should only apply values(), as the other two methods exist to maintain stability and interoperability with Map.

const set = new Set([1, 2, 3])

// Get the values of a set
set.values()
Output:

SetIterator {1, 2, 3}

Iteration with Sets

There is a forEach() method in Set as well as Map. Unlike Maps, Sets don't have keys, so forEach() returns the same value for its first and second parameters. Thus, it has no other use case than compatibility with Maps.

In order to use forEach(), you must supply its parameters (value, key, set).The forEach() and for...of functions can both be used on Sets.

Let's examine forEach() first:

const set = new Set(['apm', 'rum', 'infra'])

// Iterate a Set with forEach
set.forEach((value) => console.log(value))

Once the for...of version is written, we can write:

// Iterate a Set with for...of
for (const value of set) {  
    console.log(value);
}

In both cases, the subsequent results will be obtained:

Output:

apm
rum
infra

Properties and Methods in Set

To streamline a brief reference, the subsequent table delivers a list of Set properties and methods:

Properties/Methods

Description

Returns

add(value)

Appends a new item to a Set

Set Object

delete(value)

Removes the specified item from a Set

Boolean

has()

Checks for the presence of an item in a Set

Boolean

clear()

Removes all items from a Set

N/A

keys()

Returns all values in a Set (same as values())

SetIterator object

values()

Returns all values in a Set (same as keys())

SetIterator object

entries()

Returns all values in a Set as [value, value]

SetIterator object

forEach()

Iterates through the Set in insertion order

N/A

size

Returns the number of items in a Set

Number

Application of Sets

For working with duplicate values in data, a set is an important addition to your JavaScript toolkit. Using an Array with duplicate values, we can create a new Array without duplicate values in a single line.

let uniqueArray = [ ...new Set(["Application monitoring", "Application monitoring", "Real user monitoring", "Real user monitoring", "Real user monitoring", "infrastructure monitoring"])];

console.log(uniqueArray);

The result will be:

Output:

[ 'Application monitoring',
  'Real user monitoring',
  'infrastructure monitoring' ]

Data can be compared using a set to find the union, intersection, and difference between two sets.

Since arrays furnish the sort(), map(), filter(), and reduce() methods, as well as direct compatibility with JSON methods, they have the upper hand over sets for more evolved data manipulation.

Maps versus Sets

Both map and set in JavaScript have distinct advantages and disadvantages that make them suitable for different tasks. It is important to understand the differences between the two and when to use each one.

Maps

  • A two-dimensional collection that stores record as key-value pairs, and each key is distinctive
  • For every entry, key and value both correspond to the exact value or reference
  • Using the entries() method, the default iterator is retrieved
  • The Set.prototype object defines set() and get() methods

Sets

  • The collection stores only unique values: they are one-dimensional
  • For every entry, key and value both correspond to the exact value or reference
  • Set objects return the values() method's default iterator ([Symbol.iterator])
  • The Set.prototype object does not define the set() and get() methods; it defines the add () method.

Wrap Up - Map or Set: Which is better?

When you need your dataset to contain unique values, consider using a Set. A map is applied when there are pairs of associated data. The keys correspond to the values in map.

With map and set in JavaScript, you can clean and optimize your code more easily. Sets are collections of individual values, and maps are sets of ordered key-value pairs. The primary use of map and set in JavaScript is to support objects and arrays.

In choosing your standard built-in objects, keep these factors in mind. Despite JavaScript's ability to use multiple built-in objects, it's always best to select the one that works best for you.

With these data structures, JavaScript can perform common tasks, such as determining key/value pair collections' lengths and removing duplicate items from data sets.

While Arrays and Objects have generally been used for storing and manipulating data in JavaScript, and they are directly compatible with JSON, making them an essential part of REST API development.


Atatus Real User Monitoring

Atatus is a scalable end-user experience monitoring system that allows you to see which areas of your website are underperforming and affecting your users. Understand the causes of your front-end performance issues and how to improve the user experience.

By understanding the complicated frontend performance issues that develop due to slow page loads, route modifications, delayed static assets, poor XMLHttpRequest, JS errors, core web vitals and more, you can discover and fix poor end-user performance with Real User Monitoring (RUM).

You can get a detailed view of each page-load event to quickly detect and fix frontend performance issues affecting actual users. With filterable data by URL, connection type, device, country, and more, you examine a detailed complete resource waterfall view to see which assets are slowing down your pages.

Try your 14-day free trial of Atatus!

Pavithra Parthiban

Pavithra Parthiban

Technical Content Writer
Chennai

Monitor your entire software stack

Gain end-to-end visibility of every business transaction and see how each layer of your software stack affects your customer experience.