Continuamos analizando las novedades de ECMAScript 2015. Hoy es el turno de los Maps y los Sets: Entre otras novedades, ES6 incorpora 4 nuevas estructuras de datos, que son Map, WeakMap, Set y WeakSet. Si has trabajado con lenguajes como Java o Python ya te harás una idea de para que sirven. Vamos a repasarlos.

Map

El objecto Map nos permite relacionar (mapear) unos valores con otros como si fuera un diccionario, en formato clave/valor. Cualquier valor (tanto objetos como valores primitivos) puede ser usados como clave o valor.

Los Maps nos permiten, por ejemplo, saber de inmediato si existe una clave o borrar un par clave/valor concreto:

//ES6
let map = new Map();
map.set('foo', 123);
let user = {userId: 1};
map.set(user, 'Alex');

map.get('foo'); //123
map.get(user); //Alex

map.size; //2

map.has('foo'); //true

map.delete('foo'); //true
map.has('foo'); //false

map.clear(); 
map.size; //0

Además, podemos crear Maps a partir de un array de pares:


map = new Map([['user1','Alex'], ['user2', 'Vicky'], ['user3', 'Enrique']]); for(let [key, value] of map){ console.log(key, value); } //"user1" "Alex" //"user2" "Vicky" //"user3" "Enrique" map.keys(); //iterator with keys map.values(); //iterator with values map.entries(); //iterator with pair [key, value]

En la documentación de Mozilla sobre Map puedes ver todas las propiedades del objeto Map.

WeakMap

Los WeakMaps son similares a los Maps, pero con algunas diferencias:

  • Un WeakMap solo acepta objetos como claves
  • La referencia a las claves es débil, lo que significa que si no hay otras referencias al objeto que actúa como clave, el garbage collector podrá liberarlo.

Debido a que usa referencias débiles, un WeakMap NO dispone del método .keys() para recuperar las claves, NI de propiedades o métodos relacionados con más de un elemento a la vez, como .values(), .entries(), .clear() o .size.
Tampoco podemos iterar un WeakMap con el bucle for of.

Veamos un ejemplo práctico:

let key = {userId:1};
let key2 = {userId:2};
let weakmap = new WeakMap();

weakmap.set(key,"Alex");
weakmap.has(key); //true
weakmap.get(key); //Alex
weakmap.delete(key); // true
weakmap.get(key); //undefined

weakmap.set(key2,"Vicky");
weakmap.size; //undefined
key2=undefined;
weakmap.get(key2); //undefined

Set

Los sets son conjuntos de elementos no repetidos, que pueden ser tanto objetos, como valores primitivos.

Tiene métodos equivalentes a un Map, con la diferencia que utilizamos add para añadir elementos, y de que en un set las keys y los values son lo mismo, el valor del objeto. Del mismo modo, .entries() devuelve una pareja [value, value]

let set = new Set();
set.add('foo');
set.add('bar');
set.size  //2

for(let item of set){
  console.log(item);
}
//"foo"
//"bar"

for(let item of set.entries()){
  console.log(item);
}
//["foo", "foo"]
//["bar", "bar"]

set.has('foo');  //true
set.delete('foo');  //true
set.has('foo');  //false
set.size  //1
set.clear();
set.size  //0

Otras formas de definir un set es a través de un array o bien concatenando el método add.

let set1 = new Set(['foo', 'bar']);
for(let i of set1){
  console.log(i)
}
//foo
//bar

//remember set elements are unique
let set2 = new Set().add('foo').add('bar').add('bar');
for(let i of set2){
  console.log(i)
}
//foo
//bar

WeakSet

Nos encontramos con una situación análoga al WeakMap, pero con los Sets. Las dos principales diferencias de un WeakSet respecto a un Set son:

  • Los WeakSets únicamente pueden contener colecciones de objetos.
  • La referencia a los objetos es débil, por lo que si no hay otra referencia a uno de los objetos contenidos en el WeakSet, el garbage collector lo podrá liberar. Esto implica que:
    • No hay una lista de objetos almacenados en la colección
    • Los WeakSet no son enumerables.

Básicamente, los métodos de los que dispone un WeakSet son:

  • add()
  • delete()
  • has()
let obj = ['foo', 'bar'];
let ws = new WeakSet();
ws.add(obj);

ws.has(obj); //true

obj = undefined;
ws.has(obj); //false
ws.delete(obj); //false

Conclusiones

ES6 aporta a Javascript varias herramientas que lo ponen al nivel de otros lenguajes de programación muy potentes como Java o python. Puedes ver otras de las novedades que aporta en mi Introducción a ES6