How to add a flag 🚩 to an object without modifying it?

In programming, we often deal with objects that we retrieve from databases or external sources through APIs. In some cases, we may need to add certain flags or metadata to these objects to help us further process and analyze the data. However, it is worth remembering that modifying the original objects can lead to undesirable effects and make debugging the code more difficult. Therefore, it is worth considering the use of structures such as Map and WeakMap to store this additional information.

The problem of object modification

Let's consider an example. We have an object representing a person that we downloaded from the database:

const person = { 
firstName: "John", 
lastName: "Ragnar", 
age: 31, 
city: "Łódź"

};

Our goal is to mark this person as "online" without modifying the object itself. Often we can use a simple method like adding a flag:

person.isOnline = true;

However, this approach modifies the object, which in some situations can lead to undesirable results.

Tired of reading? Watch this video to see how Wojtek makes things quick and easy (available in Polish only).

Wyświetl ten post na Instagramie

Post udostępniony przez Ragnarson (@ragnarsoncom)

Map and WeakMap

Creating a Map:

const myMap = new Map();

A map is a data structure available in JavaScript that allows you to store a key-value pair, where keys can be any data type. Unlike ordinary objects, maps do not suffer from the problem of unexpected overwriting of existing properties. Keys in a map are unique, eliminating the risk of accidental modification or overwriting of values.

Creating a WeakMap:

const myWeakMap = new WeakMap();

A WeakMap is a special kind of map that has some limitations, but also valuable uses in certain situations. The main difference between a WeakMap and a regular Map is that the keys in a WeakMap must be objects, not arbitrary data types. Moreover, keys in a WeakMap are not immune to deletion by JavaScript's Garbage Collection (GC) mechanism. If the only object referencing a key is deleted, the key and its associated data will also be deleted, which helps avoid memory leaks.

Using WeakMap to add flags

However, instead of modifying the original object, we can use the WeakMap to store additional information.

Flag Assignment:

const personData = new WeakMap(); 
personData.set(person, { isOnline: true });

With this approach, we do not directly modify the person object, which eliminates the risk of unintentionally changing other properties. At the same time, we have access to the added flag by referring to the personData WeakMap.

const flagData = personData.get(person);
if (flagData && flagData.isOnline) {
  console.log(`${person.firstName} ${person.lastName} is online.`);
} else {
  console.log(`${person.firstName} ${person.lastName} is offline.`);
}

Summary

Avoiding direct modification of objects can help keep code readable and correct. Using Maps and WeakMap to store additional information, such as flags or metadata, avoids unwanted side effects. Maps allow different types of data to be stored as keys and values. WeakMaps, on the other hand, although they have some limitations, are useful in scenarios where we want to avoid memory leaks and no longer intend to use keys. Remember that choosing the right structure depends on the context and requirements of our project.