Map
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
El objeto Map
retiene tuplas de llave-valor y mantiene el orden de inserción de las llaves.
Cualquier valor (ambos objetos y valores primitivos) puede ser usado como llave o valor.
Pruébalo
Descripción
Los objetos Map
son colecciones de tuplas tipo llave-valor. Una llave en Map
puede aparecer solo una vez; es única en la colección de Map
. Un objeto Map
es iterado por sus tuplas llave-valor —un bucle for...of
regresa un arreglo de [llave, valor]
por cada iteración. La iteración sucede en orden de inserción, la cual corresponde al orden en el que cada tupla llave-valor fue incertada inicialmente en el map por el método set()
(eso es, si no había una llave con el mismo valor en el map, cuando set()
fué llamado).
La especificación requiere que los maps sean implementados "que, en promedio, proporcione tiempos de acceso que sean sublineales al numero de elementos en la colección". Por lo tanto, podría ser representado internamente como una tabla hash (con una busqueda O(1)), un árbol de búsqueda (con una busqueda de O(log(N))), o cualquier otra estructura de datos, mientras la complejidad sea mejor que O(N).
Igualdad de llaves
La igualdad de valores se basa en el algoritmo Igualdad SameValueZero. (Se solía usar igualdad SameValue, el cual trataba 0
y -0
como diferentes. Revise compatibilidad con navegadores.) Lo que significa que NaN
es conciderado lo mismo que NaN
(a pesar de que NaN !== NaN
) y todos los otros valores son conciderados iguales, de acuerdo a la semantica del operador ===
.
Objects vs. Maps
Object
es similar a Map
—ambos te permiten asignar llaves a valores, recuperar esos valores, borrar llaves, y detectar si hay algo guardado en una llave. Por esta razón (y porque no había alternativas incorporadas), históricamente Object
se ha usado como Map
.
Sin embargo, hay diferencias importantes que hacen que se prefiera a Map
en algunos casos:
Map | Object | |
---|---|---|
Llaves accidentales | Un objeto Map no tiene llaves por defecto. Sólo contiene lo que explicitamente se pone en él. |
Un objeto
Nota: Esto se puede evitar usando |
Seguridad | Un objeto Map es seguro de usar con llaves y valores proporcionados por el usuario. |
Asignar tuplas de llave-valor proporcionadas por el usuario en un |
Tipos de llaves |
Las llaves de un objeto Map pueden ser cualquier valor (incluyendo funciones,
objetos, o cualquier primitivo).
|
Las llaves de un objeto Object deben ser String o un Symbol . |
Orden de las llaves |
Las llaves en un objeto |
A pesar de que ahora las llaves de un objeto común
El orden en ECMAScript 2015 fué definido inicialmente para las propiedades propias del objeto; ECMAScript 2020 define un orden también para propiedades heredadas. Pero nótese que ningún mecanismo único itera todas las propiedades de un objeto; de los varios mecanismos, cada uno inluye un subconjunto diferente de propiedades; ( |
Tamaño |
El número de elementos en un Map se obtiene fácilmente de su propiedad
size .
|
Determinar el número de elementos en un Objeto es mas indirecto y menos eficiente. Una forma común de hacerlo es através de la propiedad length del arreglo que regresa la función Object.keys() . |
Iteración |
Un Map es un
iterable, así que puede ser iterado directamente.
|
Nota:
|
Desempeño |
Se desempeña mejor en escenarios que involucran adiciones y eliminaciones frecuentes de tuplas llave-valor. |
No está optimizado para adiciones y eliminaciones frequentes de tuplas llave-valor. |
Serialización y análisis de cadenas de texto |
No tiene soporte nativo para serialización o análisis de cadenas de texto.
(Pero puedes construir tu propio soporte para serialización y análisis de cadenas de texto para
|
Tiene soporte nativo para serialización de
Tiene soporte nativo para análisis de cadenas de JSON a |
Asignando propiedades de objeto
Asignar propiedades de objeto funciona también para objetos Map, y puede crear confusión.
Por lo tanto, de alguna manera esto parece funcionar:
const wrongMap = new Map();
wrongMap["bla"] = "blaa";
wrongMap["bla2"] = "blaaa2";
console.log(wrongMap); // Map { bla: 'blaa', bla2: 'blaaa2' }
Pero esta manera de asignar una propiedad, no interactua con la estructura de datos del objeto Map. Utiliza la característica de el objeto genérico. El valor 'bla' no es guardado en el Map para consultas. Otras operaciones que fallan:
wrongMap.has("bla"); // false
wrongMap.delete("bla"); // false
console.log(wrongMap); // Map { bla: 'blaa', bla2: 'blaaa2' }
El uso correcto para guardar datos en el objeto Map es através de el método set(key, value)
.
const contacts = new Map();
contacts.set("Jessie", {
telefono: "213-555-1234",
direccion: "123 N 1st Ave",
});
contacts.has("Jessie"); // true
contacts.get("Hilary"); // undefined
contacts.set("Hilary", { telefono: "617-555-4321", direccion: "321 S 2nd St" });
contacts.get("Jessie"); // {teléfono: "213-555-1234", dirección: "123 N 1st Ave"}
contacts.delete("Raymond"); // false
contacts.delete("Jessie"); // true
console.log(contacts.size); // 1
APIs del navegador similares a Map
Objetos del Navegador similares a Map
(o "objetos que parecen map") son interfaces de la API Web que se comportan en muchos aspectos como un objeto Map
.
Al igual que el objeto Map
, las entradas pueden iterarse en el mismo orden en que fueron agregadas al objeto.
Los objetos similares a Map
y los objetos Map
también tienen propiedades y métodos que comparten el mismo nombre y comportamiento. Sin embargo, contrario a los objetos Map
estos sólo permiten tipos específicos predefinidos para las llaves y valores de cada entrada.
Los tipos permitidos se encuentran en la especificación de la definición IDL (Interfaz de Descripcion del Lenguage). Por ejemplo, RTCStatsReport
es un objeto similar a Map
que debe usar cadenas de caracteres para sus llaves, y objetos para sus valores. Esto está definido en la especificación IDL a continuación:
interface RTCStatsReport {
readonly maplike<DOMString, object>;
};
Los objetos similares a Map
son o de solo-lectura o lectura-escritura (véase la palabra clave readonly
en el IDL de arriba).
- Los obejtos similares a
Map
de solo-lectura tienen la propiedadsize
, y los métodos:entries()
,forEach()
,get()
,has()
,keys()
,values()
, y[Symbol.iterator]()
. - Los objetos similares a
Map
de lectura-escritura tienen métodos adicionales:clear()
,delete()
, yset()
.
Los métodos y propiedades tienen el mismo comportamiento que las entidades equivalentes en el objeto Map
, excepto por la restricción en los tipos de llaves y valores.
Los siguientes, son ejemplos de objetos de navegador similares a Map
:
Constructor
Map()
-
Crea un nuevo objeto
Map
.
Propiedades estáticas
Map[Symbol.species]
-
La función constructor que es usada para crear objetos derivados.
Metodos estáticos
Map.groupBy()
-
Agrupa los elementos de un iterable usando los valores que regresa la función provista. El objeto
Map
que regresa, usa como llaves los valores únicos de la función de prueba, los cuales pueden ser usados para obtener el arreglo de elementos de cada grupo.
Propiedades de instancia
Estas propiedades están definidas en Map.prototype
y las comparten todas las instancias de Map
.
Map.prototype.constructor
-
La funcion constructor que creó el objeto de instancia. Para las instancias de
Map
el valor inicial es el constructorMap
. Map.prototype.size
-
Regresa el número de tuplas llave/valor en el objeto
Map
. Map.prototype[Symbol.toStringTag]
-
El valor inicial de la propiedad
[Symbol.toStringTag]
es la cadena de caracteres"Map"
. Esta propiedad es usada enObject.prototype.toString()
.
Métodos de instancia
Map.prototype.clear()
-
Remueve todas las tuplas llave-valor del objeto
Map
. Map.prototype.delete()
-
Regresa
true
si un elemento en el objetoMap
existía y ha sido removido, orfalse
si el elemento no existe.map.has(key)
regresaráfalse
después de esto. Map.prototype.entries()
-
Regresa un nuevo objeto Iterador que contiene un arreglo con dos miembros
[llave, valor]
por cada elemento en el objetoMap
en orden de inserción. Map.prototype.forEach()
-
Llama una función
callbackFn
una vez por cada tupla llave-valor presente en el objetoMap
, en orden de inserción. Si un parametrothisArg
es proporcionado aforEach
, será utilizado como el valorthis
para cada llamada a la funcion callback. Map.prototype.get()
-
Regresa el valor asociado a la llave que se pasa como argumento, o
undefined
si no hay ninguno. Map.prototype.has()
-
Regresa un booleano indicando si, en el objeto
Map
un valor ha sido asociado a la llave pasada como argumento. Map.prototype.keys()
-
Regresa un nuevo objeto Iterador que contiene las llaves para cada elemento en el objeto
Map
, en orden de inserción. Map.prototype.set()
-
Asigna el valor en el objeto
Map
para la llave pasada como argumento. Regresa el objetoMap
. Map.prototype.values()
-
Regresa un nuevo objeto Iterador que contiene los valores para cada elemento en un objeto
Map
, en orden de inserción. Map.prototype[Symbol.iterator]()
-
Regresa un nuevo objeto Iterador que contiene un arreglo con dos miembros
[llave, valor]
por cada elemento en el objetoMap
, en orden de inserción.
Ejemplos
Usando el objeto Map
const myMap = new Map();
const keyString = "a string";
const keyObj = {};
const keyFunc = function () {};
// asignando valores
myMap.set(keyString, "valor asociado con la llave 'a string'");
myMap.set(keyObj, "valor asociado con la llave keyObj");
myMap.set(keyFunc, "valor asociado con la llave keyFunc");
console.log(myMap.size); // 3
// obteniendo los valores
console.log(myMap.get(keyString)); // "valor asociado con la llave 'a string'"
console.log(myMap.get(keyObj)); // "valor asociado con la llave keyObj"
console.log(myMap.get(keyFunc)); // "valor asociado con la llave keyFunc"
console.log(myMap.get("a string")); // "valor asociado con la llave 'a string'", porque keyString === 'a string'
console.log(myMap.get({})); // undefined, porque keyObj !== {}
console.log(myMap.get(function () {})); // undefined, porque keyFunc !== function () {}
Usando NaN como llave de Map
NaN
puede también usarse como una llave. A pesar que cada NaN
no es igual a si mismo (NaN !== NaN
es verdadero), el siguiente ejemplo funciona porque los NaN
son indistinguibles entre sí:
const myMap = new Map();
myMap.set(NaN, "not a number");
myMap.get(NaN);
// "not a number"
const otherNaN = Number("foo");
myMap.get(otherNaN);
// "not a number"
Iterando Map con for...of
Los Maps pueden iterarse usando un bucle for...of
:
const myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (const [key, value] of myMap) {
console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one
for (const key of myMap.keys()) {
console.log(key);
}
// 0
// 1
for (const value of myMap.values()) {
console.log(value);
}
// zero
// one
for (const [key, value] of myMap.entries()) {
console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one
Iterando Map con forEach()
Los Maps pueden iterarse usando el método forEach()
:
myMap.forEach((value, key) => {
console.log(`${key} = ${value}`);
});
// 0 = zero
// 1 = one
Relación con objetos Array
const kvArray = [
["key1", "value1"],
["key2", "value2"],
];
// Usa el constructor ordinario Map para transformar un Array 2D llave-valor a un map
const myMap = new Map(kvArray);
console.log(myMap.get("key1")); // "value1"
// Usa Array.from() para transformar un map a un Array 2D llave-valor
console.log(Array.from(myMap)); // Mostrará exactamente el mismo Array como kvArray
// Una forma concisa de hacer lo mismo, usando la sintaxis spread
console.log([...myMap]);
// O usa los iteradores keys() o values(), y conviertelos a un arreglo
console.log(Array.from(myMap.keys())); // ["key1", "key2"]
Clonando y uniendo Maps
Así como los Array
, los Map
pueden clonarse:
const original = new Map([[1, "one"]]);
const clone = new Map(original);
console.log(clone.get(1)); // one
console.log(original === clone); // false (útil para comparaciones superficiales)
Nota: Tenga en cuenta que los datos en si no se clonan.
Los objetos Map pueden unirse, manteniendo la unicidad de las llaves:
const first = new Map([
[1, "one"],
[2, "two"],
[3, "three"],
]);
const second = new Map([
[1, "uno"],
[2, "dos"],
]);
// Al unir ambos maps. La ultima llave repetida gana.
// la sintaxis Spread convierte un Map a un Array
const merged = new Map([...first, ...second]);
console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
Los Maps también pueden unirse a Arrays:
const first = new Map([
[1, "one"],
[2, "two"],
[3, "three"],
]);
const second = new Map([
[1, "uno"],
[2, "dos"],
]);
// Merge maps with an array. The last repeated key wins.
const merged = new Map([...first, ...second, [1, "eins"]]);
console.log(merged.get(1)); // eins
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
Especificaciones
Specification |
---|
ECMAScript Language Specification # sec-map-objects |
Compatibilidad con navegadores
BCD tables only load in the browser