Skip to content

Latest commit

 

History

History
203 lines (142 loc) · 7.46 KB

map-weakmap-set.md

File metadata and controls

203 lines (142 loc) · 7.46 KB

Sure, here's how you can include the Set part:

In JavaScript, Map, WeakMap, and Set are types of collections, each with their own characteristics:

  1. Key Types: In a Map, keys can be any type, including objects, primitive values (like numbers, strings, booleans), and functions. In a WeakMap, keys must be objects. Primitive values are not allowed as keys. A Set does not have keys, it only stores unique values of any type.

  2. Key References: In a Map, keys are strongly referenced. This means that as long as the Map exists, all of its keys exist too, preventing them from being garbage collected. In a WeakMap, keys are weakly referenced. If there are no other references to an object used as a key in a WeakMap, that object can be garbage collected, which also removes the key-value pair from the WeakMap.

  3. Iterability: A Map is iterable, which means you can loop over it using methods like for...of or .forEach(). It also has a size property that gives the number of key-value pairs in the Map. A WeakMap is not iterable and does not have a size property. This is because the number of keys in a WeakMap can change as keys are garbage collected. A Set is iterable and has a size property, similar to a Map.

  4. Use Cases: Maps are generally used when you need to associate values with keys and retrieve them later. WeakMaps are used when you want to associate additional data with objects that should be removed when the object is garbage collected. This is useful for private data for an object or avoiding memory leaks in an application. Sets are used when you need to keep track of a list of unique items.

let map = new Map();
let weakmap = new WeakMap();
let set = new Set();

let obj = {};

map.set(obj, "value for map");
weakmap.set(obj, "value for weakmap");
set.add("value for set");

console.log(map.get(obj)); // Outputs: "value for map"
console.log(weakmap.get(obj)); // Outputs: "value for weakmap"
console.log(set.has("value for set")); // Outputs: true

obj = null; // Now, the object can be garbage collected

console.log([...map]); // Outputs: [ [ {}, 'value for map' ] ]
// The object still exists in the map

// But it's not possible to get the size or entries of the weakmap
console.log(set.size); // Outputs: 1

Use cases for Map

  1. Caching/Memoization: Similar to WeakMaps, Maps can be used for caching or memoization to store the results of expensive function calls and reuse them when the same inputs occur.
let cache = new Map();

function computeExpensiveValue(input) {
  if (cache.has(input)) {
    return cache.get(input);
  } else {
    let result = /* expensive computation */;
    cache.set(input, result);
    return result;
  }
}
  1. Data Grouping: Maps can be used to group data by a certain property or criteria. For example, you could use a Map to group an array of people by their city of residence.
let people = [
  { name: 'Alice', city: 'London' },
  { name: 'Bob', city: 'Paris' },
  { name: 'Charlie', city: 'London' },
];

let peopleByCity = new Map();

for (let person of people) {
  if (!peopleByCity.has(person.city)) {
    peopleByCity.set(person.city, []);
  }
  peopleByCity.get(person.city).push(person);
}
  1. Frequency Count: Maps can be used to count the frequency of elements in an array or other collection.
let array = ['apple', 'banana', 'apple', 'orange', 'banana', 'banana'];

let frequencyMap = new Map();

for (let item of array) {
  if (!frequencyMap.has(item)) {
    frequencyMap.set(item, 0);
  }
  frequencyMap.set(item, frequencyMap.get(item) + 1);
}

console.log([...frequencyMap]); // Outputs: [ ['apple', 2], ['banana', 3], ['orange', 1] ]
  1. Object Key-Value Storage: Unlike regular objects, Maps allow keys of any type, not just strings or symbols. This makes them ideal for cases where you need to associate data with objects, functions, or other non-string keys.
let map = new Map();
let objKey = {};
let funcKey = function() {};

map.set(objKey, 'Value associated with objKey');
map.set(funcKey, 'Value associated with funcKey');

console.log(map.get(objKey)); // Outputs: 'Value associated with objKey'
console.log(map.get(funcKey)); // Outputs: 'Value associated with funcKey'

In all these cases, the key benefit of using a Map over a regular object is that a Map maintains the insertion order of elements and allows keys of any type.

Use cases for WeakMap

  1. Storing Private Data: WeakMaps can be used to store private data for an object. Since the keys in a WeakMap are weakly referenced, when the object is garbage collected, the associated data in the WeakMap is also automatically removed. This is useful when you want to associate data with an object without modifying the object itself.
let privateData = new WeakMap();

function MyClass() {
  privateData.set(this, { secret: 'My secret data' });
}

MyClass.prototype.getSecret = function() {
  return privateData.get(this).secret;
};

let instance = new MyClass();
console.log(instance.getSecret()); // Outputs: "My secret data"
  1. Managing Memory: WeakMaps can be used to manage memory in applications that need to keep track of large objects. Since the keys in a WeakMap are weakly referenced, they can be garbage collected when not in use, which can help prevent memory leaks.
let cache = new WeakMap();

function cacheData(obj, data) {
  if (!cache.has(obj)) {
    cache.set(obj, data);
  }
}

let largeObject = {};
cacheData(largeObject, { data: 'A lot of data...' });

largeObject = null; // The large object and its associated data can now be garbage collected
  1. Memoization: WeakMaps can be used for memoization, which is a technique used to speed up consecutive function calls by caching the result of calls with identical input. In this case, the function's parameters are used as the key and the result is the value.
let memo = new WeakMap();

function heavyComputation(obj) {
  if (memo.has(obj)) {
    return memo.get(obj);
  } else {
    let result = /* expensive computation */;
    memo.set(obj, result);
    return result;
  }
}

In all these cases, the key benefit of using a WeakMap over a Map is that the garbage collector can automatically clean up the entries in the WeakMap when they are no longer needed, which can help manage memory and prevent memory leaks.

Use cases for Set

  1. Storing Unique Values: Sets can be used to store unique values. When you add a value to a Set that's already in the Set, it won't be added again.
let set = new Set();

set.add(1);
set.add(2);
set.add(1);

console.log(set.size); // Outputs: 2
  1. Checking Membership: Sets can be used to quickly check if a value is in the Set.
let set = new Set();

set.add(1);

console.log(set.has(1)); // Outputs: true
console.log(set.has(2)); // Outputs: false
  1. Set Operations: Sets can be used to perform set operations like union, intersection, and difference.
let set1 = new Set([1, 2, 3]);
let set2 = new Set([3, 4, 5]);

let union = new Set([...set1, ...set2]);
let intersection = new Set([...set1].filter(x => set2.has(x)));
let difference = new Set([...set1].filter(x => !set2.has(x)));

console.log([...union]); // Outputs: [1, 2, 3, 4, 5]
console.log([...intersection]); // Outputs: [3]
console.log([...difference]); // Outputs: [1, 2]

In all these cases, the key benefit of using a Set is that it allows you to keep track of unique items and perform set operations.