Map

Este artigo necessita de uma revisão técnica. Como posso ajudar.

O objeto Map é um mapa simples de chave/valor. Qualquer valor (objeto e valores primitivos) pode ser usado como uma chave ou um valor.

Sintaxe

new Map([iterable])

Parâmetros

iterable

Iterable é um Array ou outro objeto iterável cujos elementos são pares de chave-valor (2-element Arrays). Cada par de chave-valor é adicionado ao novo Map. null é tratado como undefined.

Descrição

Um objeto Map itera seus elementos em ordem de inserção — um loop for...of retorna um array de [chave, valor] para cada iteração.

Igualidade de valores

A igualdade das chaves é baseada no algoritmo "same-value" (mesmo valor): NaN é considerado igual à NaN (mesmo que NaN !== NaN) e todos os outros valores são considerados iguals de acordo com a semantica do operador ===. Em versões anteriores do rascunho ECMAScript 6 -0 e +0 eram considerados diferentes (mesmo que -0 === +0), isto foi trocado em versões posteriores e foi aplicado no Gecko 29 (Firefox 29 / Thunderbird 29 / SeaMonkey 2.26) (bug 952870) e em uma build recente nightly do Chrome.

Objetos e mapas comparados

Objects são similares a Maps onde ambos deixam adicionar chaves para valores, recuperar estes valores, apagar chaves, e detectar quando algo foi adicionado em uma chave. Por causa disso (e porquê não existem alterativas pré-construidas), Objects historicamente foram usados como Maps; no entento, existem diferenças importantes entre Objects e Maps que fazem o uso do Map melhor:

  • Um Object tem um prototype, então existem chaves padrão no mapa. Isto pode ser evitado usando um Map = Object.create(null) desde ES5, mas raramente é feito.
  • As chaves de um Object são Strings e Symbols, porém elas podem ser qualquer valor em um Map.
  • Você pode obter o tamanho de um  Map facilmente enquanto em um Object é necessário ter este controle manualmente.

Isto não significa que você deve usar Maps em todo lugar, objetos ainda serão usados na maioria dos casos. Instancias de Map são úteis somente para coleções, e você deve considerar adaptar seu codigo onde você usou objetos para isto anteriormente. Objects devem ser usados como registros, com campos e métodos.
Se você não tem certeza qual usar, pergunte-se as seguintes questões:

  • As keys são desconhecidas até o tempo de execução, você precisa procurá-las dinamicamente?
  • Todos os valores sempre serão do mesmo tipo, e podem ser usados de forma intercambiável?
  • Você precisa de keys que não são strings?
  • Os pares key-value são adicionados ou removidos frequentemente?
  • Você tem uma quantidade de pares key-value arbitrária (de troca fácil) ?
  • A coleção é iterada?

Estes são os sinais de que você quer um  Map para a coleção. Se ao invés disto você tem um numero fixo de keys, trabalhe eles individualmente, e faça diferenciação entre o uso deles, você quer um objeto.

Propriedades

Map.length
O valor da propriedade length é 0.
get Map[@@species]
A função contrutor que é usada para criar objetos derivados.
Map.prototype
Representa o prototype para o construtor de Map. Permite a adição de propriedades para todos os objetos Map.

Instancias de Map

Todas as instancias de Map herdam de Map.prototype.

Propriedades

Map.prototype.constructor
Returns the function that created an instance's prototype. This is the Map function by default.
Map.prototype.size
Returns the number of key/value pairs in the Map object.

Métodos

Map.prototype.clear()
Removes all key/value pairs from the Map object.
Map.prototype.delete(key)
Removes any value associated to the key and returns the value that Map.prototype.has(key) would have previously returned. Map.prototype.has(key) will return false afterwards.
Map.prototype.entries()
Returns a new Iterator object that contains an array of [key, value] for each element in the Map object in insertion order.
Map.prototype.forEach(callbackFn[, thisArg])
Calls callbackFn once for each key-value pair present in the Map object, in insertion order. If a thisArg parameter is provided to forEach, it will be used as the this value for each callback.
Map.prototype.get(key)
Returns the value associated to the key, or undefined if there is none.
Map.prototype.has(key)
Returns a boolean asserting whether a value has been associated to the key in the Map object or not.
Map.prototype.keys()
Returns a new Iterator object that contains the keys for each element in the Map object in insertion order.
Map.prototype.set(key, value)
Sets the value for the key in the Map object. Returns the Map object.
Map.prototype.values()
Returns a new Iterator object that contains the values for each element in the Map object in insertion order.
Map.prototype[@@iterator]()
Returns a new Iterator object that contains an array of [key, value] for each element in the Map object in insertion order.

Exemplos

Usando o objeto Map

var myMap = new Map();

var keyString = "uma string",
    keyObj = {},
    keyFunc = function () {};

// configurando os valores
myMap.set(keyString, "valor associado com 'uma string'");
myMap.set(keyObj, "valor associado com keyObj");
myMap.set(keyFunc, "valor associado com keyFunc");

myMap.size; // 3

// obtendo os valores
myMap.get(keyString);    // "valor associado com 'uma string'"
myMap.get(keyObj);       // "valor associado com keyObj"
myMap.get(keyFunc);      // "valor associado com keyFunc"

myMap.get("uma string");   // "valor associado com 'uma string'"
                         // porquê keyString === 'uma string'
myMap.get({});           // undefined, porquê keyObj !== {}
myMap.get(function() {}) // undefined, porquê keyFunc !== function () {}

Usando NaN como Map keys

NaN pode também ser usado como key. Mesmo que NaN não seja igual a ele mesmo (NaN !== NaN é true), o seguinte exemplo funciona, porquê NaNs são indistinguíveis uma para o outro:

var myMap = new Map();
myMap.set(NaN, "not a number");

myMap.get(NaN); // "not a number"

var otherNaN = Number("foo");
myMap.get(otherNaN); // "not a number"

Iterando Maps com for..of

Maps podem ser iterados usando um for..of :

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

for (var key of myMap.keys()) {
  console.log(key);
}
// Will show 2 logs; first with "0" and second with "1"

for (var value of myMap.values()) {
  console.log(value);
}
// Will show 2 logs; first with "zero" and second with "one"

for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

Iterando Maps com forEach()

Maps podem ser iterados usando um forEach():

myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

Relação com objetos Array

var kvArray = [["key1", "value1"], ["key2", "value2"]];

// Use the regular Map constructor to transform a 2D key-value Array into a map
var myMap = new Map(kvArray);

myMap.get("key1"); // returns "value1"

// Use the spread operator to transform a map into a 2D key-value Array.
console.log(uneval([...myMap])); // Will show you exactly the same Array as kvArray

// Or use the spread operator on the keys or values iterator to get 
// an array of only the keys or values
console.log(uneval([...myMap.keys()])); // Will show ["key1", "key2"]

Especificações

Especificação Status Comentário
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Map' in that specification.
Standard Definição inicial.
ECMAScript 2017 Draft (ECMA-262)
The definition of 'Map' in that specification.
Draft  

Compatibilidade com os navegadores

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support

38 [1]

13 (13) 11 25 7.1
Constructor argument: new Map(iterable) 38 13 (13) Não suportado 25 Não suportado
iterable 38 17 (17) Não suportado 25 7.1
Map.clear() 31
38
19 (19) 11 25 7.1
Map.keys(), Map.values(), Map.entries() 37
38
20 (20) Não suportado 25 7.1
Map.forEach() 36
38
25 (25) 11 25 7.1
Key equality for -0 and 0 34
38
29 (29) Não suportado 25 Não suportado
Constructor argument: new Map(null) (Yes) 37 (37) ? ? ?
Monkey-patched set() in Constructor (Yes) 37 (37) ? ? ?
Map[@@species] ? 41 (41) ? ? ?
Map() without new throws ? 42 (42) ? ? ?
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support Não suportado 38 [1] 13.0 (13) Não suportado Não suportado 8
Constructor argument: new Map(iterable) Não suportado 38 13.0 (13) Não suportado Não suportado Não suportado
iterable Não suportado Não suportado 17.0 (17) Não suportado Não suportado 8
Map.clear() Não suportado 31
38
19.0 (19) Não suportado Não suportado 8
Map.keys(), Map.values(), Map.entries() Não suportado 37
38
20.0 (20) Não suportado Não suportado 8
Map.forEach() Não suportado 36
38
25.0 (25) Não suportado Não suportado 8
Key equality for -0 and 0 Não suportado 34
38
29.0 (29) Não suportado Não suportado Não suportado
Constructor argument: new Map(null) ? (Yes) 37.0 (37) ? ? ?
Monkey-patched set() in Constructor ? (Yes) 37.0 (37) ? ? ?
Map[@@species] ? ? 41.0 (41) ? ? ?
Map() without new throws ? ? 42.0 (42) ? ? ?

[1] Começando com Chrome 31, a feature ficou disponível sob modificação de configurações. Em chrome://flags, ative a entrada activate “Enable Experimental JavaScript”.

Ver também

Etiquetas do documento e colaboradores

 Colaboradores desta página: BernardoMariano, raduq, raphaelpor
 Última atualização por: BernardoMariano,