Los maps son un tipo estructura de datos introducida en la especificación ES6. Estas no son mas que una forma de mantener una lista de pares de clave y valor de forma similar a ‘hash tables’ o ‘diccionarios’ en otros lenguajes de programación como por ejemplo Python o C#.

Un Map() es solo una colección de elementos donde cada uno de estos se almacena en el formato de pares clave/valor. En esta estructura se puede utilizar cualquier tipo definido en el lenguaje como una clave o como un valor. Este proporciona una API simple para almacenar objetos mediante una clave arbitraria. Son como una mezcla entre Arrays y Objetos.

Antes de ES6 una de las formas de tener este tipo de estructuras era por medio de los objetos, estos nos permitían asignar claves a valores de cualquier tipo y aparentemente funcionaba todo bien, pero realmente habían algunas deficiencias y efectos no deseados al momento de extender el uso de esta estructura.

Diferencias entre los Maps y Objetos en JavaScript

A primera vista los mapas parecen ser similares a los objetos de JavaScript pero realmente tienen algunas diferencias notables:

  1. Los objetos están limitados a usar solamente strings o symbols como claves, mientras que los Maps pueden usar cualquier tipo de dato.
  2. Los objetos tienen métodos a los que se puede llamar y prototipos que se pueden usar para crear una cadena de herencia, mientras que los mapas se centran únicamente en el almacenamiento y la recuperación de pares clave/valor.
  3. Cuando utilizamos un Map se nos hace fácil saber el tamaño del este, es decir, saber el número de pares clave – valor que contiene. En un objeto no existe un propiedad para esto.
  4. En los objetos podemos acceder directamente al valor de las propiedades, mientras que los mapas se limitan al uso del método get() para recuperar cualquier valor en este.
  5. Los Map mantienen sus elementos pares en orden como en los Arrays y tienen muchos métodos de iteración para trabajar con estos.

Ahora, para crear un map u objeto de mapa vacío utilizamos el operador new y el constructor Map(): (Cabe decir que hasta el momento no existe una notación literal para crear estos mapas)

const roles = new Map();

Si analizamos la estructura anterior en consola podemos notar que la variable colores es ahora una instancia del objeto Map pero su tipo es un Objetc. Veamos:

console.log( roles );
console.log( typeof( roles ) );
console.log( roles instanceof Map );
// Map(0){}
"object"
true

Métodos de los Maps

Generalmente los métodos en Javascript son acción que ejecutamos sobre los datos de un objeto en especifico. En este caso veremos que método acompañan a este tipo de estructura.

Añadir de entradas a un Map

Podemos utilizar el método set() para agregar un par de clave y valor a un mapa. El primer valor es la clave y el segundo por supuesto es el valor:

mapa.set(a, b)
// Añadir entradas
roles.set('pedro', 'administrador');
roles.set('josue', 'editor');
roles.set('diego', 'autor');

El anterior ejemplo nos devuelve en consola lo siguiente:

Map(3) {"pedro" => "administrador", "josue" => "editor", "diego" => "autor"}

El valor de retorno muestra la asignación con la clave conectada al valor utilizando el símbolo ‘cohete hash’ o flecha gorda (=>)

También podemos encadenar el método set() para agregar múltiples propiedades a la estructura Map:

roles.set().set().set();
Si deseamos saber el numero de elemetos o los pares clave – valor establecidos en el Map podemos utilizar la propiedad size.

console.log( roles.size );
// 3

Obtener valores en un Map

Un Map en JavaScript básicamente es como un diccionario donde podemos buscar un valor basado en una clave. Para buscar este valor podemos usar el método get():

mapa.get(a)

En sus parámetros especificamos especificamos la clave cuyo valor debe devolverse. Este devolverá el valor asociado a dicha clave si esta presente en la estructura de lo contrario el valor a devolver será undefinided.

roles.get("pedro");
roles.get("Edgardo");
"administrador"
undefined

Verificar claves en un Map

El método has() lo podemos usar para verificar si una clave en particular está en un mapa. Esto devuelve un valor booleano de verdadero o falso en consecuencia a la coincidencia. En sus parámetros especificamos la clave del elemento a verificar.

roles.has("josue");
roles.has(100);
true
false

Obtener todas las claves de un Map

Para obtener todas las claves de un Map utilizamos el metodo keys(). Este metodo devuelve un objeto iterador que nos devolverá todas las claves de todos los elementos contenidos en una estructura Map.

En el siguiente ejemplo utilizaremos una estructura que nos ayudará a iterar sobre el resultado que nos devuelve el método keys() en el Map roles. Para esto utilizaremos la estructura for of:

for ( let rol of roles.keys() ){
  console.log( rol )
}
"pedro"
"josue"
"diego"

Una de las ventaja que los Map() tienen sobre los objetos es el cómo podemos iterar sobre ellos. Están diseñados para ser iterados de forma fácil con métodos como los .forEachy un protocolo de iterador para usar con ciclos for..of

Obtener todos los valores de un Map

Al igual que keys() el método values() nos devuelve un objeto iterador que contiene todos los valores presentes en el objeto Map.

for ( let rol of roles.values() ){
  console.log( rol )
}
"administrador"
"editor"
"autor"

Obtener las claves y valores de un Map

Con entries() podremos obtener un objeto iterador donde vendrán contenidos cada par [key,values] de elementos en el objeto Map. Por su puesto para iterar sobre el objeto devuelto por entries utilizamos nuevamente la estructura for of.

for ( let rol of roles.entries() ){
  console.log(`El usuario ${rol[0]} es ${rol[1]}`);
}
"El usuario pedro es administrador"
"El usuario josue es editor"
"El usuario diego es autor"

Eliminar entradas de un Map

El método delete() se puede usar para eliminar tanto la clave como el valor de un Map. Esto devuelve un valor booleano de verdadero si el valor se eliminó o falso si no estaba en el mapa. Para eliminar un valor específico, debe especificar la clave entre paréntesis:

roles.delete("diego");
true

Eliminar todos los elementos de un Map

El método clear() eliminará todos los pares de clave y valor de un Map. Este no acepta parámetros y el valor que devolverá será undefinided.

roles.clear();
console.log( roles )
Map(0) {}

Convertir un Map a un array

Si debemos convertir un Map a un Array para hacer algo que de pronto vemos complicado hacer con el objeto Map y vemos que puede ser mejor con algún método de los arrays podemos hacerlo de un par de métodos. Ambos nos crearan un array multidimensional.

  1. Utilizando el método Array.from()
  2. Utilizando el spread operator o operador de propagación.
console.log( Array.from(roles)  );
// o tambien
console.log( [...roles] );
[["pedro", "administrador"], ["josue", "editor"], ["diego", "autor"]]

El resultado es el mismo.

Un buen ejemplo de cuando debemos de utilizar estos Mapas es cuando tenemos la posibilidad de agregar metadatos a objetos existentes o cuando debemos adjuntar algunos datos adicionales a objetos inmutables. Estos pueden ser de gran ayuda.


Palabras finales: Hay muchas situaciones en las que debemos de decidir que tipo de estructurar debemos de utilizar, todo depende de lo que vayamos a hacer y de como lo queremos hacer, por ejemplo. Si necesita iterar sobre un objeto o deseamos que las claves de la estructura no sean solo cadenas, los Maps son la mejor opción. Si la estructura será simple y estática (sin agregar o eliminar propiedades) entonces un Objeto podría ser la mejor opción.

Mas informacion:
https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Map