ES6 of the Week

This Week's Episode:

maps and sets

Maps and Sets

  • In JavaScript, objects wear many hats:
    • We use objects as HashMaps or dictionaries, as well as instances of classes
  • Sometimes, if we know we want to store data in a certain way, it may be safer and more efficient to use a different data structure than the JS engine's implementation of objects
  • Enter: Maps and Sets

Sets

  • Sets are a collection of unique values of any type
    • This includes object references
  • Items in a Set will be iterated through in the order they were inserted
  • Because each item in the set is unique, you can check their equality at a high level (i.e. if you compare an item in a Set that references a specific object in memory, it will evaluate as equal to another pointer to that same object in memory

On your mark, get set...

let _set = new Set(); // n.b. set is a reserved word, so I'm calling my variable _set

// Set.prototype.add
_set.add("string").add(42);

// store object references
let obj = { a : 1 };
_set.add(obj);

// Set.prototype.size
_set.size // => 3
_set.add(42) // no repeats
_set.size // => 3

// Set.prototype.has
_set.has("string") // true
_set.has(obj) // true, wowzers!
_set.has(21) // false

// Iterate using for...of
for (let item of _set) console.log(item); // logs in insertion order

// Set.prototype.delete and Set.prototype.clear
_set.delete("string"); // remove a single item
_set.clear(); // wipe the set clean

Arrays

Could have duplicates

 

Actually an object

 

Iterate with for loop

Sets

Unique values

 

No baggage

 

Iterate with for...of

Maps

  • A key-value map
  • Keys can contain object references, functions, or whatever
  • No need to worry about Object.hasOwnProperty when iterating
  • Has handy methods that make it easy to get the size, or iterate over either the values or keys

Objects

Has a prototype (default key)

 

Keys are strings or symbols

 

Cannot get size easily

Maps

No prototype

 

Keys are any type

 

Can get size easily

Follow the Map!

let _map = new Map(); // now I'm just being consistent ;)

// Map.prototype.set
_map.set('a', 1);
_map.set('b', 2);

let objKey = { 'c' : 3 };
_map.set(objKey, 4);

// Map.prototype.get
_map.get('a'); // => 1
_map.get(objKey); // => 4

// Map.prototype.size - much easier than using Object.hasOwnProperty!
_map.size; // => 3

// Iterate over keys using Map.prototype.keys
for (let key of _map.keys()) console.log(key);

// Iterate over values using Map.prototype.values
for (let value of _map.values()) console.log(value);

WeakSet and WeakMap

  • Have a subset of the same Set/Map methods/properties (but not all)
    • WS: Add, has, delete
    • WM: Get, set, has delete
  • WeakSets can only contain objects, and the keys of WeakMaps can only be objects
  • Objects in WeakSets and WeakMaps are weakly held, meaning that if no other reference to them exists, they will be garbage collected
    • Advantageous for freeing up memory
    • This also means they are not enumerable (not iterable)

WeakMap example

let _counter = new WeakMap();
let _action = new WeakMap();

class Countdown {
    constructor(counter, action) {
        _counter.set(this, counter);
        _action.set(this, action);
    }
    dec() {
        let counter = _counter.get(this);
        if (counter < 1) return;
        counter--;
        _counter.set(this, counter);
        if (counter === 0) {
            _action.get(this)();
        }
    }
}

// http://www.2ality.com/2015/01/es6-maps-sets.html

Use Cases

  • Set
    • Any collection of unique values
  • Map
    • Quite versatile
    • Dictionary-like collections, especially those that will be iterated over
  • WeakSet
    • 'branding' your classes?
  • WeakMap
    • storing metadata for an object
    • prevent memory leaks in the DOM
    • http://stackoverflow.com/questions/29413222/what-are-the-actual-uses-of-es6-weakmap

Resources

  • ES6: http://es6-features.org/
  • Wiki: https://en.wikipedia.org/wiki/Object_(computer_science)
  • Mozilla docs:
    • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
    • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
    • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet
    • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
  • Blogs & StackOverflow
    • http://bjorn.tipling.com/maps-sets-and-iterators-in-javascript
    • http://www.sitepoint.com/preparing-ecmascript-6-set-weakset/
    • http://stackoverflow.com/questions/29413222/what-are-the-actual-uses-of-es6-weakmap
    • https://esdiscuss.org/topic/actual-weakset-use-cases
    • http://www.2ality.com/2015/01/es6-maps-sets.html

ES6 of the Week - 5

By Tom Kelly

ES6 of the Week - 5

Maps and Sets

  • 1,607