Seleccionar página
Como conclusión a nuestra serie de artículos donde hemos explicado algunas posibles extensiones de Map y Set, os proponemos dar un repaso a otras propuestas ampliación del estándar de estos objetos y a librerías bastante completas y probadas que extienden estos objetos con nuevas funcionalidades.

Propuestas de ampliación del estándar (TC39)

Vamos a revisar las propuestas que se han presentado ante el comité TC39, el organismo dedicado a la estandarización de Javascript, para ampliar los objetos Set y Map.

Extensión de Set (Stage 2)

https://github.com/tc39/proposal-set-methods

A la fecha de publicación de este artículo hay una propuesta al TC39 para ampliar el objeto Set con nuevos métodos basados en la gestión de conjuntos. Esta propuesta está en estado 2 y todavía pueden sufrir bastantes cambios, incluso no llegar a ser parte del estándar, pero nos ofrece una perspectiva sobre lo que se están plateando para un futuro más o menos próximo.

Si no queremos esperar a que se estandaricen y generalicen estas funciones, podemos crear una clase heredada de Set que incluya los mismos métodos que esta propuesta incluye:

class ExtSet extends Set {

  intersection (iterable) {
    const newSet = new (Object.getPrototypeOf (this).constructor) ();
    for (let e of iterable) {
      if (this.has (e)) {
        newSet.add (e);
      }
    }
    return newSet;
  }

  union (iterable) {
    const newSet = new (Object.getPrototypeOf (this).constructor) (this);
    for (let e of iterable) {
      newSet.add (e);
    }
    return newSet;
  }

  difference (iterable) {
    const newSet = new (Object.getPrototypeOf (this).constructor) (this);
    for (let e of iterable) {
      newSet.delete (e);
    }
    return newSet;
  }

  symmetricDifference (iterable) {
    const newSet = new (Object.getPrototypeOf (this).constructor) (this);
    for (let e of iterable) {
      newSet.delete (e) || newSet.add (e);
    }
    return newSet;
  }

  isSubsetOf (iterable) {
    if (typeof iterable.has !== 'function') {
      iterable = new Set (iterable);
    }
    for (let e of this) {
      if (!iterable.has (e)) {
        return false;
      }
    }
    return true;
  }

  isSupersetOf (iterable) {
    for (let e of iterable) {
      if (!this.has (e)) {
        return false;
      }
    }
    return true;
  }

  isDisjointFrom (iterable) {
    for (let e of iterable) {
      if (this.has (e)) {
        return false;
      }
    }
    return true;
  }

}

Extensión de Map y Set (Stage 1)

https://github.com/tc39/proposal-collection-methods

Hay otra propuesta al TC39 para ampliar los objetos Map y Set con nuevos métodos similares a los que encontramos en Array. Al está en estado 1 es muy difícil saber si serán finalmente parte del estándar o se producirán cambios muy sustanciales.

Aquí incluimos varias de estas funcionalidades, similares a las que provee Array, en una clase que hereda de Map:

class ExtMap extends Map {

  every (callback, thisArg) {
    const iterator = this[ Symbol.iterator ] ();
    let step;
    while (!(step = iterator.next ()).done) {
      if (!callback.call (thisArg || this, step.value[ 1 ], step.value[ 0 ], this)) {
        return false;
      }
    }
    return true;
  }

  filter (callback, thisArg) {
    const newMap   = new (Object.getPrototypeOf (this).constructor) ();
    const iterator = this[ Symbol.iterator ] ();
    let step;
    while (!(step = iterator.next ()).done) {
      if (callback.call (thisArg || this, step.value[ 1 ], step.value[ 0 ], this)) {
        newMap.set (step.value[ 0 ], step.value[ 1 ]);
      }
    }
    return newMap;
  }

  find (callback, thisArg) {
    for (let element of this) {
      if (callback.call (thisArg || this, element[ 1 ], element[ 0 ], this)) {
        return element;
      }
    }
  }

  findKey (callback, thisArg) {
    for (let element of this) {
      if (callback.call (thisArg || this, element[ 1 ], element[ 0 ], this)) {
        return element[ 0 ];
      }
    }
  }

  map (callback, thisArg) {
    const newMap   = new (Object.getPrototypeOf (this).constructor) ();
    const iterator = this[ Symbol.iterator ] ();
    let step;
    while (!(step = iterator.next ()).done) {
      let result = callback.call (thisArg || this, step.value[ 1 ], step.value[ 0 ], this);
      newMap.set (result[ 0 ], result[ 1 ]);
    }
    return newMap;
  }

  reduce (callback, initialValue) {
    const iterator = this[ Symbol.iterator ] ();
    let step;
    while (!(step = iterator.next ()).done) {
      initialValue = callback(initialValue, step.value[ 1 ], step.value[ 0 ], this);
    }
    return initialValue;
  }

  some (callback, thisArg) {
    const iterator = this[ Symbol.iterator ] ();
    let step;
    while (!(step = iterator.next ()).done) {
      if (callback.call (thisArg || this, step.value[ 1 ], step.value[ 0 ], this)) {
        return true;
      }
    }
    return false;
  }
}

Librerías

Hay un buen número de librerías y paquetes que amplían y complementan la funcionalidad de Map y Set. Aquí recogemos dos de las más populares e interesantes, pero os animamos a explorar otras opciones más allá de estas que os proponemos.

Inmutable

https://immutable-js.github.io/immutable-js/

Esta interesante librería se basa en la idea utilizar sólo datos inmutables, es decir, que no se pueden cambiar una vez creados, lo que lleva a un desarrollo mucho más simple y confiable. Por ello todas las funciones que producirían cambios en los datos generan nuevos objetos con los datos actualizados, pero nunca modifican los datos originales.

Immutable proporciona muchas estructuras de datos persistentes e inmutables que incluyen: List, Stack, Map, OrderedMap, Set, OrderedSet, Record, una versión lazy de Seq, etc.

Immutable es una librería extremadamente popular y tiene millones de descargas semanales en NPM, dando soporte tanto a Javascript como a Flow y Typescript, con una documentación bastante completa.

Collections JS

http://www.collectionsjs.com/

Esta librería proporciona una completa implementación para manejar colecciones en Javascript, con características bastante útiles. Estas colecciones proporcionan alternativas a los objetos estándar de Javascript.

CollectionsJS incluye la capacidad de observar todos los cambios y tener una interfaz común en cada colección, implementando métodos genéricos, muchos ya conocidos de Array, y otros nuevos que complementan la funcionalidad.

Ofrece implementaciones de List, Object, Map, FastMap, LruMap, LfuMap, SortedMap, SortedArrayMap, Dict, MultiMap, WeakMap, Deque, Array, Set, FastSet, LruSet, LfuSet, SortedSet, SortedArraySet, SortedArray, Heap e Iterator.

CollectionJS es una librería muy probada y ampliamente difundida, por lo que su uso es bastante recomendable. Su documentación es muy fácil de consultar, a pesar de la gran cantidad de objetos y métodos que incluye la librería.

Conclusiones

En esta serie de artículos hemos mostrado algunas de las capacidades que podemos añadir a Map y Set para que se comporten de la forma que nos interesa en cada caso. Las posibilidades son prácticamente infinitas. Podemos manejar estas simples estructuras de datos con nuevas funcionalidades por medio de la herencia nos abre una vía de exploración muy atractiva que os invitamos a continuar.

Como se puede ver, ya hay librerías bastante completas que han ampliado y ajustado estos objetos estándar a diferentes contextos y funcionalidades. Construir estas funcionalidades por nosotros mismos tampoco es complicado y hemos aportado diferentes ejemplos de ello. Mantener nuestros datos en estructuras bien formadas y organizadas nos ofrece un gran control sobre los mismos, sin que por ello tengamos que perder necesariamente el rendimiento de las soluciones más simples.

Esperamos haber provocado cierta curiosidad en vosotros y exploréis las capacidades de extensión de Map y Set.

Novedades

Datos inmutables en Javascript

Datos inmutables en Javascript

En Javascript todo parece mutable, es decir, que se puede cambiar, pero lo cierto es que también nos ofrece varios mecanismos para conseguir que los datos que manejamos, especialmente los objetos, sean inmutables. Te invitamos a descubrir cómo…

Copiar objetos en Javascript

Copiar objetos en Javascript

Copiar objetos no es algo sencillo, incluso se podría decir que en si mismo no es posible, ya que el concepto «copiar» no entra dentro del paradigma de los objetos. No obstante, por medio de instrucciones como Object.assign() hemos aprendido como obtener objetos con las mismas propiedades, pero está técnica no se puede aplicar a todos los tipos de objetos disponibles en Javascript. Vamos a ver cómo podemos copiar cualquier tipo de objeto…

Descubre los Javascript Array Internals

Descubre los Javascript Array Internals

El Array es una de las estructuras más utilizadas en Javascript y no siempre bien comprendida. Hoy os invitamos a analizar el comportamiento interno de este objeto y descubrir cómo Javascript implementa las diferente acciones con los Array y que operaciones internas se realizan en cada caso.

Web Components: pasado, presente y futuro

Web Components: pasado, presente y futuro

Los Web Components aparecieron en el panorama de desarrollo hace ya bastante tiempo. Desde su presentación se les ha prestado mucha atención, pero lo cierto es que no han sido acogidos de forma generalizada, quizás por la difusión de nuevos y potentes frameworks. Nos preguntamos qué ha pasado con este estándar y, sobre todo, que puede pasar de aquí en adelante con el uso práctico de los componentes web.