Mapas vs Objetos en ES6, ¿Cuándo usarlo?

83

Ref: Mapas MDN

Utilice mapas sobre objetos cuando las claves sean desconocidas hasta el momento de la ejecución y cuando todas las claves sean del mismo tipo y todos los valores sean del mismo tipo.

Utilice objetos cuando haya una lógica que opere sobre elementos individuales.

Pregunta:

¿Cuál es un ejemplo aplicable del uso de mapas sobre objetos? en particular, "¿cuándo se desconocerán las claves hasta el tiempo de ejecución?"

var myMap = new Map();

var keyObj = {},
    keyFunc = function () { return 'hey'},
    keyString = "a string";

// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

console.log(myMap.get(keyFunc));
Matthew Harwood
fuente
Sí, lo noté. Como configuro una función como valor. @JonathanLonowski, ¿puedes pensar en cuándo debería hacer eso ?:( es difícil pensar en casos de uso.
Matthew Harwood
7
Puede usarlo donde tenga, por ejemplo, un elemento DOM con el que desea asociar algunos datos con el uso de un Objeto. En lugar de usar, diga el ID del elemento como clave en un objeto, puede usar el elemento en sí como clave en un mapa para que no le importe si el elemento tiene un ID (o cualquier otro identificador único que no sea una referencia de objeto ) o no.
RobG
1
@RobG solo una pequeña adición: en ese caso es una WeakMapque también podría ser útil.
zerkms
1
Creo que esto sugiere usar objetos como / para registros y mapas para cualquier otro tipo de mapeo. Con registros me refiero a una estructura de datos con un conjunto fijo de campos, como un objeto de usuario que tiene los campos namey, idpor ejemplo.
Felix Kling
1
Cuando estaba leyendo esa página de MDN, la lista de casos de uso con viñetas fue mucho más útil que el párrafo que citó. Ciertamente en relación con la pregunta planteada en su título.
CodingIntrigue

Respuestas:

51

¿Cuál es un ejemplo aplicable del uso de mapas sobre objetos?

Creo que ya ha dado un buen ejemplo: al menos necesita usar Maps cuando está usando objetos (incluidos los objetos de función) como claves.

en particular, "¿cuándo se desconocerán las claves hasta el tiempo de ejecución?"

Siempre que no se conozcan en el momento de la compilación. En resumen, siempre debe usar a Mapcuando necesite una colección de valores clave . Un buen indicador de que necesita una colección es cuando agrega y elimina valores dinámicamente de la colección, y especialmente cuando no conoce esos valores de antemano (por ejemplo, son leídos de una base de datos, ingresados ​​por el usuario, etc.).

Por el contrario, debería utilizar objetos cuando sepa cuáles y cuántas propiedades tiene el objeto mientras escribe el código, cuando su forma es estática. Como lo ha dicho @Felix: cuando necesitas un registro . Un buen indicador de la necesidad es cuando los campos tienen diferentes tipos y cuando nunca es necesario utilizar la notación entre corchetes (o esperar un conjunto limitado de nombres de propiedades).

Bergi
fuente
1
O desde otro punto de vista: siempre que necesite iterar sobre las propiedades de su objeto en el nivel de datos (por ejemplo for..of) en lugar del nivel de programa (por ejemplo for..in) utilice a Map. Más información sobre estos términos en esta respuesta .
Agregaré como comentario también el hecho de que cada vez que no sepa qué tipo de clave será y no espera cadenas como tipos de datos clave, use map stackoverflow.com/questions/32600157/…
Carmine Tambascia
26

Creo que con ES2015 Mapsolo quedan dos razones para usar objetos planos:

¿Cuándo no es importante el orden de propiedad?

  • si solo tiene un valor único y algunas funciones que deberían asociarse explícitamente con él (como Promise, que es un proxy para un valor futuro, y then/ catch)
  • si tiene una estructura de datos similar a una estructura / registro con un conjunto estático de propiedades conocidas en el "tiempo de compilación" (por lo general, las estructuras / registros no son iterables)

En todos los demás casos, podría considerar usarlo Map, porque conserva el orden de las propiedades y separa el programa (todas las propiedades asignadas al Mapobjeto) del nivel de datos (todas las entradas en el Mapmismo).

¿Cuáles son los inconvenientes de Map?

  • pierde la sintaxis literal del objeto conciso
  • necesita reemplazos personalizados para JSON.stringyfy
  • pierde la desestructuración, que es más útil con estructuras de datos estáticos de todos modos

fuente
Esta línea me preocupa mucho: "probablemente sea más lento que los objetos puros, tipo hashmap" Pensé en reemplazar todos mis objetos con mapas debido a mejoras en el rendimiento. Pero dices que es más lento ...
mesqueeb
1
Tienes razón. Mapes probablemente más rápido, porque se basa puramente en un hash, mientras que Objectes un poco más complicado. ¡Gracias!
11

Utilice mapas sobre objetos cuando las claves sean desconocidas hasta el momento de la ejecución y cuando todas las claves sean del mismo tipo y todos los valores sean del mismo tipo.

No tengo idea de por qué alguien escribiría algo tan obviamente mal. Tengo que decir que la gente encuentra cada vez más contenido incorrecto y / o cuestionable en MDN en estos días.

Nada en esa oración es correcto. La razón principal para usar mapas es cuando desea claves con valores de objeto. La idea de que los valores deberían ser del mismo tipo es absurda, aunque podría serlo, por supuesto. La idea de que uno no debería usar objetos cuando las claves son desconocidas hasta el tiempo de ejecución es igualmente absurda.


fuente
1
No veo qué tiene de absurdo la idea. Cuando necesita colecciones, por lo general se escriben estrictamente (puede haber excepciones, por supuesto). Además, creo que dejar de usar objetos para colecciones (cuando Mapesté disponible) es un buen consejo.
Bergi
El hecho de que las colecciones estén típicamente escritas de forma estricta es lógicamente distinto de decir que algo estrictamente escrito debería ser una colección.
1
Sí, creo que es un poco extraño, pero la idea está bien. Supongo que pensaron que "las claves son desconocidas hasta el tiempo de ejecución" ya hace una colección. ¿Alguna idea para una mejor redacción?
Bergi
1
Convenido. MDN tiene muy buena documentación, pero deberían ceñirse a la documentación de las API y no intentar dar consejos de programación.
AlexG
5

Una de las diferencias entre Mapy Objectes:

Mappuede utilizar tipos de datos complejos como clave. Me gusta esto:

const fn = function() {}
const m = new Map([[document.body, 'stackoverflow'], [fn, 'redis']]);

m.get(document.body) // 'stackoverflow'
m.get(fn) //'redis'

cuidado: para tipos de datos complejos, si desea obtener el valor, debe pasar la misma referencia que la clave.

Object, solo acepta el tipo de datos simple ( number, string) como clave.

const a = {};
a[document.body] = 'stackoverflow';

console.log(a) //{[object HTMLBodyElement]: "stackoverflow"}
diapositivasp2
fuente
2

Esta pregunta es un duplicado de pero hasta que esté cerrado, aquí está mi respuesta desde allí :

Además de las otras respuestas, descubrí que los mapas son más difíciles de manejar y más detallados para operar que los objetos.

obj[key] += x
// vs.
map.set(map.get(key) + x)

Esto es importante, porque el código más corto es más rápido de leer, más directamente expresivo y mejor mantenido en la cabeza del programador .

Otro aspecto: como set () devuelve el mapa, no el valor, es imposible encadenar asignaciones.

foo = obj[key] = x;  // Does what you expect
foo = map.set(key, x)  // foo !== x; foo === map

La depuración de mapas también es más dolorosa. A continuación, no puede ver qué claves hay en el mapa. Tendrías que escribir código para hacer eso.

Buena suerte evaluando un iterador de mapas

Los objetos pueden ser evaluados por cualquier IDE:

WebStorm evaluando un objeto

Dan Dascalescu
fuente
6
Esto no responde a la pregunta " ¿Cuál es un ejemplo aplicable del uso de Maps sobre objetos? " En absoluto
Bergi
6
Por favor, no publiques tus respuestas. Y no, la pregunta no es un duplicado.
Bergi
1

ObjectLos s son similares a los Maps en el sentido de que ambos le permiten establecer claves en valores, recuperar esos valores, eliminar claves y detectar si algo está almacenado en una clave. Debido a esto (y porque no había alternativas integradas), Objects se han utilizado como Maps históricamente; sin embargo, existen diferencias importantes que hacen que sea Mappreferible usar un en ciertos casos:

  • Las claves de an Objectson Strings y Symbols, mientras que pueden tener cualquier valor para a Map, incluidas funciones, objetos y cualquier primitiva.
  • Las claves de entrada Mapestán ordenadas, mientras que las claves agregadas al objeto no. Por lo tanto, al iterar sobre él, un Mapobjeto devuelve claves en el orden de inserción.
  • Puede obtener el tamaño de un Mapfácilmente con la sizepropiedad, mientras que el número de propiedades en un Objectdebe determinarse manualmente.
  • A Mapes iterable y, por lo tanto, se puede iterar directamente, mientras que iterar sobre un Objectrequiere obtener sus claves de alguna manera e iterar sobre ellas.
  • An Objecttiene un prototipo, por lo que hay claves predeterminadas en el mapa que podrían colisionar con sus claves si no tiene cuidado. A partir de ES5, esto se puede evitar mediante el uso map = Object.create(null), pero rara vez se hace.
  • A Mappuede funcionar mejor en escenarios que implican la adición y eliminación frecuentes de pares de claves.

MDN

codejockie
fuente