Keyed collections

Estás leyendo la versión en inglés del artículo porque aún no existe una traducción para este idioma. ¡Ayúdanos a traducir este artículo!

Este capítulo introduce las colecciones de datos las cuales son ordenadas mediante una clave; los objetos Map y Set contienen elementos cuya iteración se da conforme al orden de inserción.

Maps

El objeto Map

ECMAScript 6 introduce una nueva estructura de datos para mapear valores a valores. Un objeto Map es un simple mapeo clave/valor y puede iterar sobre sus elementos en el orden de inserción.

El siguiente código muestra algunas operaciones básicas con un Map. Para ver más ejemplos,  y la referencia de la API completa, mira la página de referencia Map . Puedes usar un bucle for...of para devolver un array de [ clave, valor] en cada iteración.

var sonidos = new Map();
sonidos.set("perro", "guau");
sonidos.set("gato", "miau");
sonidos.set("oveja", "beee");
sonidos.size; // 3
sonidos.get("zorro"); // undefined
sonidos.has("pájaro"); // false
sonidos.delete("perro");

for (var [clave, valor] of sonidos) {
  console.log(clave + " hace " + valor);
}
// "gato hace miau"
// "oveja hace beee"

Comparación de Object y Map

Tradicionalmente, objects ha sido usado para mapear strings a valores. Los objetos te permiten establecer claves con valores, recuperar esos valores, borrar las claves, y detectar si algo es almacenado como una clave. Los objetos Map, sin embargo, poseen ciertas ventajas sobre los objectos Object que los hacen mejores.

  • Las claves de un Object son Strings, mientras que en un  Map las claves pueden ser de cualquier tipo.
  • Se puede obtener el tamaño de un Map fácilmente mientras en un Object se debe realizar un registro manual para obtenerlo.
  • La iteración sobre mapas se produce en el orden en que se insertaron los elementos en el mapa.
  • Un Object tiene un prototipo, por eso existen claves por defecto en el map. Esto puede evitarse haciendo  map = Object.create(null)).

Estos dos consejos pueden guiarte a la hora de decidir si usar un Map o un Object:

  • Usa mapas preferiblemente cuando las claves son desconocidas hasta el tiempo de ejecución, o cuando todas las claves son del mismo tipo y todos los valores son del mismo tipo.
  • Usa objetos cuando sea lógico operar sobre elementos individuales.

El objeto WeakMap

El objeto WeakMap es una colección de pares clave/valor en la cual sólamente las claves son objetos y los valores pueden ser valores arbitrarios. La referencia a los objetos en las claves se mantienen débilmente, lo que significa que son objetivo del recolector de basura si no hay otra referencia al objeto. La API de WeakMap es la misma que la API de Map.

Una diferencia con los objetos Map, es que las claves de WeakMap no son enumerables (no existe un método que devuelva una lista con las claves). Si lo fuesen, la lista dependería del estado de la recolección de basura, introduciendo no-determinismo.

Para más información y códigos de ejemplo, veáse también "¿Por qué WeakMap?" en la página de referencia WeakMap.

Un caso de uso de los objetos WeakMap es almacenar datos privados para un objeto u ocultar detalles de implementación. El siguiente ejemplo es del artículo de Nick Fitzgerald "Hiding Implementation Details with ECMAScript 6 WeakMaps". Los datos y métodos privados son almacenados en el objeto WeakMap denominado privates. Todo lo expuesto en la instancia y el prototipo es público; todo lo demás es inaccesible desde el mundo exterior ya que privates no es exportado junto al módulo.

const privates = new WeakMap();

function Public() {
  const me = {
    // Private data goes here
  };
  privates.set(this, me);
}

Public.prototype.method = function () {
  const me = privates.get(this);
  // Do stuff with private data in `me`...
};

module.exports = Public;

Sets

Objeto Set

Los objetos Set son colecciones de valores. Puedes iterar sus elementos en el orden de inserción. Un valor en un Set sólo puede tener lugar una vez; es único en la colección del Set.

El código siguiente muestra algunas operaciones básicas con un Set. Consulte también la página de referencia de Set  para ver más ejemplos y la API completa.

var mySet = new Set();
mySet.add(1);
mySet.add("some text");
mySet.add("foo");

mySet.has(1); // true
mySet.delete("foo");
mySet.size; // 2

for (let item of mySet) console.log(item);
// 1
// "some text"

Conversión entre Array y Set

Puedes crear un Array desde un Set usando Array.from o el operador de propagación (spread operator). Además, el constructor de Set acepta un Array para convertirlo en la otra dirección. Note nuevamente que los objetos Set almacenan valores únicos, así que cualquier elemento duplicado de un Array es eliminado cuando se realiza la conversión.

Array.from(mySet);
[...mySet2];

mySet2 = new Set([1,2,3,4]);

Array y Set comparados

Tradicionalmente - en Javascript - un conjunto de elementos han sido almacenados en arrays en un gran número de circuntancias. El nuevo objeto Set, sin embargo, tiene algunas ventajas:

  • Comprobar si un elemento existe en una colección usando indexOf en arrays es lento.
  • Los objetos Set te permiten eliminar elementos por su valor. Con un array tendrías que usar splice basado en el índice de un elemento.
  • El valor NaN no puede encontrarse con indexOf en un array.
  • Los objetos Set almacenan valores únicos, no tienes que controlar duplicados por ti mismo.

Objeto WeakSet

Los objetos WeakSet son colecciones de objetos. Un objeto en el WeakSet sólo puede tener lugar una vez; es único en la colección. Los objectos del WeakSet no son enumerables.

Las principales diferencias con los objetos Set son:

  • En contraste a los Sets, los WeakSets son colecciones de objetos únicamente y no de tipos de datos arbitrarios.
  • El WeakSet es débil: Las referencias a objetos en la colección se mantienen débilmente. De no haber otra diferencia a un objeto almacenado en el WeakSet, éste puede ser eliminado por el recolector de basura, lo que significa que no hay una lista de los objetos actualmente almacenados en la colección. Los WeakSets no son enumerables.

Los casos de uso de WeakSet son limitados. No provocarán fugas de memoria, así que - por ejemplo - puede ser seguro usar elementos DOM como clave y marcarlos para fines de seguimiento.

Igualdad Clave y valor de Map y Set

Tanto la igualdad de clave en objetos Map como la igualdad de valor en objetos Set, están basados en "same-value-zero algorithm":

  • La igualdad funciona igual que el operador de comparación de identidad: ===
  • -0 y +0 son considerados iguales.
  • NaN es considerado igual a sí mismo (al contrario que ===).