Novedades ES6

Novedades de ES6 - Map

Otra novedades de ES6 es la posibilidad del objeto Map almacena pares clave/valor. Cualquier valor (tanto objetos como valores primitivos) pueden ser usados como clave o valor.

Un objeto Map puede iterar sobre sus elementos en orden de inserción. Un bucle for..of devolverá un array de [clave, valor] en cada iteración.

Cabe destacar que un Map el cual es un mapa de un objeto, especialmente un diccionario de diccionarios, solo se va a mapear en el orden de inserción del objeto — el cual es aleatorio y no ordenado.

Objetos y mapas comparados

Los Objetos son similares a los Maps en cuanto a que ambos permiten establecer claves a valores, recuperar dichos valores, eliminar claves, y detectar si existe algo almacenado en una clave determinada. Por esto, los Objects han sido usados históricamente como Maps; no obstante, hay diferencias importantes entre  Objects y Maps que hacen mejor usar un  Map  en la mayoría de casos.

  • Las claves de un Object son Strings y Symbols, mientras que para un Map pueden ser de cualquier tipo, incluyendo funciones, objetos y cualquier otro tipo primitivo.
  • Puedes saber facilmente el tamaño de un Map usando la propiedad size, mientras que le número de propiedades en un Object tiene que ser deternminado manualmente.
  • Un Map es un iterable lo que permite iterar directamente sobre el, mientras que si queremos iterar sobre un Object necesitamos obtener primero las claves de alguna forma para después iterar sobre el.
  • Un Object tiene prototipo, por lo que hay claves por defecto en tu mapa que pueden colisionar con tus claves si no eres cuidadoso. En el estandard ES5 esto se puede evitar usando mapa = Object.create(null), pero esto raramente se hace.

Con la llegada de ES6 se presenta un nuevo objeto llamado 'Map' que nos evita tener que implementar desde cero una estructura de datos tipo diccionario o mapa.

La estructura de datos tipo 'Map' utiliza una clave para acceder a un valor.

Podemos relacionarlo con conceptos que conocemos:

  • Un diccionario tradicional que conocemos podemos utilizar un 'Map' para representarlo. La clave sería la palabra y el valor sería la definición de dicha palabra.

  • Una agenda personal también la podemos representar como un diccionario. La fecha sería la clave y las actividades de dicha fecha sería el valor.

  • Un conjunto de usuarios de un sitio web podemos almacenarlo en un diccionario. El nombre de usuario sería la clave y como valor podríamos almacenar su mail, clave, fechas de login etc.

Como clave se puede utilizar cualquier tipo de dato primitivo como también de tipo objeto. Podemos almacenar como valor también datos primitivos como objetos.

Creación de un Map.

  1. Podemos crear un Map vacío y posteriormente añadir elementos al mapa mediante el método 'set':

    <!DOCTYPE html>
    <html>
    
    <head>
      <title>Ejemplo de JavaScript</title>
      <meta charset="UTF-8">
    </head>
    
    <body>
      <script>
        const mapa1 = new Map();
        mapa1.set("casa", "house");
        mapa1.set("rojo", "red");
        mapa1.set("auto", "car");
        console.log(mapa1);
      </script>
    </body>
    
    </html>
    

    Utilizamos el método log del objeto console para mostrar el contenido del mapa (recordar que en Chrome y FireFox debemos presionar la tecla 'F12' para que se muestre la ventana de la console):

    Map javascript
  2. Podemos crear un Map e inmediatamente pasar los datos iniciales en el constructor del mismo:

      <script>
        const mapa1 = new Map([
          ["casa", "house"],
          ["rojo", "red"],
          ["auto", "car"]
        ]);
        console.log(mapa1);
      </script>
    

Recuperar el valor para una determinada clave.

Para recuperar un valor para una determinada clave del 'Map' disponemos del método 'get'.

Problema

Ingresar por teclado una palabra en castellano y posteriormente mostrar su traducción al inglés.

<!DOCTYPE html>
<html>

<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>

<body>
  <script>
    const mapa1 = new Map([
      ["casa", "house"],
      ["rojo", "red"],
      ["auto", "car"]
    ]);
    const palcastellano = prompt("Ingrese una palabra en castellano:", "");
    document.write(`La traducción de ${palcastellano} es ${mapa1.get(palcastellano)}`);
  </script>
</body>

</html>

Como podemos comprobar al ejecutar el algoritmo si ingresamos una palabra que existe en el 'Map' luego el método get nos retorna el valor para dicha palabra. Si ingresamos una palabra que no existe el método nos retorna el valor 'undefined'.

Disponemos de otro método en el objeto 'Map' llamado 'has' que le debemos pasar como parámetro una clave y en el caso que exista nos retorna true, en caso negativo nos retorna false. Luego podemos modificar nuestra aplicación para que nos muestre un mensaje en el caso que no exista la traducción de la palabra ingresada:

 <script>
    const mapa1 = new Map([
      ["casa", "house"],
      ["rojo", "red"],
      ["auto", "car"]
    ]);
    const palcastellano = prompt("Ingrese una palabra en castellano:", "");
    if (mapa1.has(palcastellano))
      document.write(`La traducción de ${palcastellano} es ${mapa1.get(palcastellano)}`);
    else
      document.write(`No existe una traducción para la palabra ${palcastellano}`)
  </script>

Tamaño del Map.

Mediante la propiedad 'size' podemos conocer la cantidad de entradas almacenadas en el mapa:

 <script>
    const mapa1 = new Map([
      ["casa", "house"],
      ["rojo", "red"],
      ["auto", "car"]
    ]);
    mapa1.set("ventana","window");
    console.log(mapa1.size);    // 4
  </script>

Eliminación de elementos del Map.

Podemos eliminar elementos mediante el método 'delete':

 <script>
    const mapa1 = new Map([
      ["casa", "house"],
      ["rojo", "red"],
      ["auto", "car"]
    ]);
    mapa1.delete("casa");
    console.log(mapa1.size);    // 2
  </script>

El método 'delete' retorna true si se eliminó la entrada en el Map y false en caso que le hayamos pasado una clave que no exista.

Para eliminar todos los elementos del mapa disponemos del método 'clear':

  <script>
    const mapa1 = new Map([
      ["casa", "house"],
      ["rojo", "red"],
      ["auto", "car"]
    ]);
    mapa1.clear();
    console.log(mapa1.size);    // 0
  </script>

Recorrido de un Map.

Los elementos almacenado en el 'Map' mantienen el orden en que se agregaron.

Podemos recorrer un mapa mediante la estructura repetitiva 'for of':

<!DOCTYPE html>
<html>

<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>

<body>
  <script>
    const mapa1 = new Map([
      ["casa", "house"],
      ["rojo", "red"],
      ["auto", "car"]
    ]);

    document.write("Claves del mapa.<br>")
    for (let clave of mapa1.keys()) {
      document.write(clave);
      document.write("<br>");
    }
    document.write("Valores del mapa.<br>")
    for (let valor of mapa1.values()) {
      document.write(valor);
      document.write("<br>");
    }
    document.write("Claves y valores del mapa.<br>")
    for (let [clave, valor] of mapa1) {
      document.write(clave + '-' + valor);
      document.write("<br>");
    }    
  </script>
</body>

</html>

Al ejecutar el algoritmo podemos ver como recorrer el mapa y recuperar en forma individual solo las claves como los valores, pero también podemos recuperar en forma simultanea las claves y valores del diccionario:

Map for of javascript

El objeto Map igual que el objeto Array dispone de un método 'forEach' para iterar sobre los elementos del 'Map':

  <script>
    const mapa1 = new Map([
      ["casa", "house"],
      ["rojo", "red"],
      ["auto", "car"]
    ]);

    document.write("Claves y valores del mapa.<br>")
    mapa1.forEach((valor, clave) => document.write(`${clave}  ${valor}<br>`));
  </script>