Getting started with javascript Map

Getting started with javascript Map

The Map data structure stores key-value pairs and remembers the order in which the keys were inserted. Any value, whether an object or a primitive value, can be used as either a key or a value.

The internal implementation of a Map object in JavaScript varies depending on the JavaScript engine. In general, a Map is typically implemented as a has table or a variant of a hash table, which is a data structure that allows for efficient key-value pair insertion, deletion, and lookup. The Map object is similar to a plain javascript object, but there are some key differences.

The one key difference is that while keys in a Map can be any data type, including objects and primitive values like strings, numbers, and booleans, keys in a plain JavaScript object can only be strings on symbol.

Another significant difference is that Maps preserves the original order in which the keys were inserted, whereas plain object properties do not. Maps also includes several built-in methods for working with data, including has(), set(), get(), forEach(), keys(), values() and entries().

Examples

A few examples of how JavaScript Map can be used to solve real-world problems:

Counting the number word appears in a string

const text = 'The qucik brown fox jumps over the lazy dog'
// split text by white space
const words = text.split(/\s+/)
// initiazlied a Map
const wordCount = new Map()
// iterate the words
for (const word of words) {
  const count = wordCount.has(word) ? wordCount.get(word) : 0
  wordCount.set(word, count + 1)
}
console.log(wordCount);
/**
 * Map { 
 * 'The' => 1, 
 * 'quick' => 1, 
 * 'brown' => 1, 
 * 'fox' => 1, 
 * 'jumps' => 1, 
 * 'over' => 1, 
 * 'the' => 1, 
 * 'lazy' => 1, 
 * 'dog' => 1 
 * }
 * */

In above example, the Map object is used to count the instances of each word in the string. Using regular expression, we split the string into an array of words. Then, we iterate over the words, adding each word to the Map object and increasing its count if it already exists.

Implementing a memoization cache for a function

Memoization is a programming optimization technique that makes applications more efficient and thus faster. It accomplishes this by caching computation results and retrieving that same information from the cache the next time it is required rather than computing it again.

function expensiveOperation(arg) {
  // simulate an expensive computation
  return new Promise(resolve => setTimeout(function() {
    resolve(arg + 1)
  }, 5000))
}

const cache = new Map()

async function memoizedFunction(arg) {
  if (cache.has(arg)) {
    return cache.get(arg)
  }

  const res = await expensiveOperation(arg)
  cache.set(arg, res)
  return res
}

(async function() {
  console.time('1st operation')
  console.log(await memoizedFunction(58)) // 59
  console.timeEnd('1st operation') // 5.007s
  console.time('2nd operation')
  console.log(await memoizedFunction(58)) // 59 from cache
  console.timeEnd('2nd operation') //0.064ms
})()

In above example, we use the Map object to implement a memoization cache for a time-consuming operation. The 'getData' method first determines whether the result for the given argument is already cached in the Map. If it is, the cached result is returned. If not, it uses the expensive function to compute the result, caches it in the Map, and returns it.

Serialization

Unlike plain JavaScript Object, Map does not have native support for serialization to JSON, which is a common data interchange format used in web applications. You might need to convert a Map to an object or use the 'JSON.stringify' replacer argument.

// Define a custom serializer for Map objects
const mapSerializer = (key, value) => {
  if (value instanceof Map) {
    const obj = {};
    for (let [k, v] of value) {
      obj[k] = v;
    }
    return obj;
  }
  return value;
};

// Create a new Map object
const map = new Map();
map.set("name", "Alice");
map.set("age", "25");

// Serialize the Map to JSON using the custom serializer
const jsonString = JSON.stringify(map, mapSerializer);
console.log(jsonString);
// {"name": "Alice", "age": 25}

In above example, we define a custom mapSerializer function that determines whether or not the value being serialized is a Map object. If that's the case, the Map is converted to a plain JavaScript object by creating a new object and adding each key-value pair from the Map to it. If the value is not a Map object, it is returned as is.