web-dev-qa-db-fra.com

Comment convertir un objet simple en une carte ES6?

Pour une raison quelconque, je ne trouve pas cette chose simple dans la documentation MDN (peut-être me manque-t-il).

Je m'attendais à ce que cela fonctionne:

const map = new Map({foo: 'bar'});

map.get('foo'); // 'bar'

... mais la première ligne jette TypeError: (var)[Symbol.iterator] is not a function

Comment créer une carte à partir d'un objet simple? Dois-je vraiment d'abord le convertir en un tableau de tableaux de paires clé-valeur?

73
callum

Oui, le constructeur Map prend un tableau de paires clé-valeur.

Object.entries est une nouvelle méthode statique d'objet disponible dans ES2017 (19.1.2.5) .

const map = new Map(Object.entries({foo: 'bar'}));

map.get('foo'); // 'bar'

Il est actuellement implémenté dans Firefox 46+ et Edge 14+ et les versions plus récentes de Chrome

Si vous devez prendre en charge des environnements plus anciens et que la transpilation n'est pas une option pour vous, utilisez un polyfill, comme celui recommandé par georg:

Object.entries = typeof Object.entries === 'function' ? Object.entries : obj => Object.keys(obj).map(k => [k, obj[k]]);
103
nils

Veuillez voir la réponse de nils en utilisant Object.entries et/ou la réponse de bergi en utilisant une fonction de générateur . Bien que Object.entries ne soit pas encore dans les spécifications lorsque la question a été posée, c'était à l'étape 4 , il est donc sans danger de le polyfiller et de l'utiliser dès avril 2016 (seulement). (Plus d'informations sur les étapes ici .) Et les fonctions du générateur étaient dans ES2015. Le PO a spécifiquement demandé d’éviter les intermédiaires et, bien que le générateur ne l’évite pas complètement, il fait un meilleur travail que celui ci-dessous ou (légèrement) Object.enties.

FWIW, en utilisant Object.entries:

  • Crée un tableau de tableaux [name, value] à transmettre à new Map
  • Le constructeur Map appelle une fonction du tableau pour obtenir un itérateur. le tableau crée et retourne un objet interator de tableau.
  • Le constructeur Map utilise cet objet itérateur pour obtenir les entrées (les tableaux [name, value]) et construire la carte.

En utilisant le générateur:

  • Crée un objet générateur à la suite de l'appel de la fonction génératrice
  • Le constructeur Map appelle une fonction sur cet objet générateur pour en obtenir un itérateur; l'objet générateur renvoie lui-même
  • Le constructeur Map utilise l'objet générateur (en tant qu'itérateur) pour obtenir les entrées (les tableaux [name, value]) et construire la carte.

Donc: Un intermédiaire de moins (le tableau de Object.entries).

Cependant, utiliser Object.entries est plus simple et créer ce tableau n’est pas un problème 99,999% du temps. Alors vraiment, l'un ou l'autre. Mais ils sont tous deux meilleurs que ceux ci-dessous. :-)


Réponse originale:

Pour initialiser une Map, vous pouvez utiliser n'importe quel itérateur qui renvoie des paires clé/valeur sous forme de tableaux, tels qu'un tableau de tableaux:

const map = new Map([
    ['foo', 'bar']
]);

Il n'y a pas de conversion intégrée d'objet en mappage, mais cela se fait facilement avec Object.keys:

const map = new Map();
let obj = {foo: 'bar'};
Object.keys(obj).forEach(key => {
    map.set(key, obj[key]);
});

Vous pouvez bien sûr vous attribuer une fonction de travailleur pour gérer cela:

function buildMap(obj) {
    let map = new Map();
    Object.keys(obj).forEach(key => {
        map.set(key, obj[key]);
    });
    return map;
}

Ensuite

const map = buildMap({foo: 'bar'});

Ou voici une version plus l33t (est-ce encore une chose?):

function buildMap(obj) {
    return Object.keys(obj).reduce((map, key) => map.set(key, obj[key]), new Map());
}

(Oui, Map#set renvoie la référence à la carte. Certains diront qu'il s'agit d'un abus de reduce.)

Ou nous pouvons vraiment aller au-dessus de l'obscurité:

const buildMap = o => Object.keys(o).reduce((m, k) => m.set(k, o[k]), new Map());

Non, je ne ferais jamais ça pour de vrai. :-)

69
T.J. Crowder

Dois-je vraiment d'abord le convertir en un tableau de tableaux de paires clé-valeur?

Non, un itérateur de tableaux de paires clé-valeur suffit. Vous pouvez utiliser ce qui suit pour éviter de créer le tableau intermédiaire:

function* entries(obj) {
    for (let key in obj)
        yield [key, obj[key]];
}

const map = new Map(entries({foo: 'bar'}));
map.get('foo'); // 'bar'
26
Bergi

La réponse de Nils décrit comment pour convertir des objets en cartes, ce que j'ai trouvé très utile. Cependant, le PO se demandait également où se trouvent ces informations dans la documentation MDN. Même s’il n’était peut-être pas présent lorsque la question a été posée à l’origine, elle se trouve maintenant sur la page MDN pour Object.entries () sous la rubrique Conversion d’un objet en carte qui indique:

Conversion d'un objet en carte

Le constructeur new Map() accepte une valeur itérable de entries. Avec Object.entries, vous pouvez facilement convertir de Object à Map:

const obj = { foo: 'bar', baz: 42 }; 
const map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }
8
Andrew Willems
const myMap = new Map(
    Object
        .keys(myObj)
        .map(
            key => [key, myObj[key]]
        )
)
6
Ohar

Sinon, vous pouvez utiliser la méthode lodash toPairs :

const _ = require('lodash');
const map = new Map(_.toPairs({foo: 'bar'}));
4
Maurits Rijk

ES6

convertir un objet en carte:

const objToMap = (o) => new Map(Object.entries(o));

convertir la carte en objet:

const mapToObj = (m) => [...m].reduce( (o,v)=>{ o[v[0]] = v[1]; return o; },{} )

Remarque: la fonction mapToObj suppose que les clés de la carte sont des chaînes (sinon, elles échoueront)

1
Yair Levy

Avec l’aide de JQuery, 

const myMap = new Map();
$.each( obj, function( key, value ) {
myMap[key] = value;
});
0
Patrick Mutuku