Est-il utile d'utiliser ES6 Map lorsque toutes les chaînes sont des chaînes?

36

Les clés d'objet standard doivent être des chaînes, alors qu'un Mappeut avoir des clés de n'importe quel type.

Mais j'ai peu d'utilité pour cela dans la pratique. Dans presque tous les cas, je me retrouve quand même à utiliser des chaînes comme clés. Et new Map()est probablement plus lent que {}. Alors, y a-t-il une autre raison pour laquelle il serait peut-être préférable d'utiliser un Mapobjet simple au lieu d'un simple?

callum
la source
3
MDN , comme d’habitude, a une bonne comparaison.
Chris Hayes
1
Pour votre information, la carte semble être plus rapide pour le réglage et l’obtention.
mardi
@mpen - jsperf est en panne maintenant. Êtes-vous sûr que map.set('foo', 123)exécuté plus vite que obj.foo = 123? Si c'est très surprenant
callum
@ Callum Uhh..no, pas positif. Vous voudrez peut-être écrire de nouveaux tests de performance.
Mpen

Réponses:

42

Il existe certaines raisons pour lesquelles je préfère utiliser Maps plutôt que des objets simples ( {}) pour stocker des données d'exécution (caches, etc.):

  1. La .sizepropriété me permet de savoir combien d'entrées existent dans cette carte;
  2. Les différentes méthodes d'utilité - .clear(), .forEach(), etc;
  3. Ils me fournissent des itérateurs par défaut!

Tous les autres cas, comme passer des arguments de fonction, stocker des configurations, etc., sont tous écrits en utilisant des objets simples.

Rappelez-vous également: n'essayez pas d'optimiser votre code trop tôt. Ne perdez pas votre temps à faire des points de repère entre un objet simple et Cartes, sauf si votre projet souffre de problèmes de performances.

Gustavohenke
la source
1
Quelle est la fonction de hashcode d'identité utilisée par Javascript?
Pacerier
1
@Pacerier ===:)
gustavohenke le
Les cartes sont beaucoup plus rapides que les objets ordinaires de nos jours.
jayarjo
@ gustavohenke Ce n'est pas vrai. Maputilise l'algorithme SameValueZero. developer.mozilla.org/en-US/docs/Web/JavaScript/…
lolmaus - Andrey Mikhaylov
@ lolmaus-AndreyMikhaylov d'accord, mais est-ce que j'ai déjà dit quelque chose à propos de l' Maputilisation de ceci ou de cela?
Gustavohenke
4

Je ne suis pas sûr de cela, mais je pense que les performances ne constituent PAS une raison pour utiliser Maps. Jetez un oeil à cette page jsperf mise à jour:

http://jsperf.com/es6-map-vs-object-properties/73

Il semble que (quand il s'agit de chaînes au moins), les objets sont beaucoup plus rapides que les cartes pour le paramétrage de base et l'obtention.

starlogodaniel
la source
2
Ce n'est pas comme ça que vous écrivez des tests de performance.
Qix
6
Ce n'est pas comme ça que vous écrivez des commentaires utiles. N'hésitez pas à préciser si vous avez une autre méthode à suggérer. Qu'est-ce qui ne va pas, en particulier, dans la rédaction de ces tests? Sont-ils en quelque sorte invalides ou inutiles?
starlogodaniel
9
La sémantique / les constructions de langage testées via des microbenchmarks ne doivent différer que d'une variable. Vos tests varient selon le nombre d'itérations, et le contenu de la boucle interne de certains d'entre eux sera optimisé car le résultat est inutilisé. Certains tests pré-déclarent des variables tandis que d'autres ont la déclaration de variable en ligne avec la boucle for, ce qui peut entraîner des anomalies de performances différentes.
Qix
1
Ouch, vous avez absolument raison. Pour ma défense, la version ma était une amélioration par rapport à la précédente, mais le contenu de la pré-déclaration et du contenu de la boucle interne a été optimisé. Je travaillais avec un collègue qui a amélioré mon brouillon et je pense avoir résolu ces problèmes: jsperf.com/es6-map-vs-object-properties/88 . Cependant, je pense qu’il est valide d’avoir différents styles de boucle pour les différentes structures de données; en utilisation réelle, les utilisateurs choisiront la structure de boucle la plus performante, et Map et Object auront différentes structures de boucles "optimales". Quoi qu'il en soit, merci pour la capture.
starlogodaniel
Ok, je vois maintenant - ils étaient plus lents que les objets ordinaires, mais ils ont été fortement optimisés dans les navigateurs récents.
Jayarjo
0

Les autres réponses ne mentionnent pas une dernière différence entre les objets et Maps:

L' Mapobjet contient des paires clé-valeur et mémorise l'ordre d'insertion d'origine des clés .

Ainsi, lors de son itération, un objet Map renvoie les clés dans l'ordre d'insertion.

Citation de MDN , mon accentuation


C'est la raison principale pour laquelle j'ai décidé d'utiliser Mappour la première fois un projet récent. J'avais un objet normal que je devais afficher dans un <table>, avec chaque propriété allant dans une ligne spécifique.

let productPropertyOrder = [ "name", "weight", "price", "stocked" ];

let product =
{
    name: "Lasagne",
    weight: "1kg",
    price: 10,
    stocked: true
}

J'ai écrit une fonction pour transformer un objet en Mapfonction d'un ordre de clé souhaité:

function objectToMap( obj, order )
{
    let map = new Map();

    for ( const key of order )
    {
        if ( obj.hasOwnProperty( key ) )
        {
            map.set( key, obj[ key ] );
        }
    }

    return map;
}

Ensuite, la carte pourrait être itérée dans l'ordre souhaité:

let productMap = objectToMap( product, productPropertyOrder );

for ( const value of productMap.values() )
{
    let cell = document.createElement( "td" );
    cell.innerText = value;
    row.appendChild( cell );
}

Bien sûr, ceci est un peu artificiel car on pourrait tout aussi bien afficher lors d'une itération sur l'ordre des propriétés sans créer Mapde processus en cours:

for ( const key of productPropertyOrder )
{
    if ( product.hasOwnProperty( key ) )
    {
        let value = product[ key ];
        // create cell
    }
}

Mais si vous avez un tableau de ces objets et que vous les affichez à plusieurs endroits, il est alors logique de les convertir tous en cartes.

WD40
la source