JavaScript Map e Set
Neste capítulo, você aprenderá sobre Map e Set em JavaScript, estruturas de dados que ampliam as capacidades da linguagem e simplificam tarefas comuns.
Este capítulo aborda duas coleções indexadas introduzidas no JavaScript moderno: Map (pares chave-valor) e Set (valores únicos). Você aprenderá o que elas fazem, quando utilizá-las em vez de objects simples e arrays, como iterar sobre elas e os padrões que você usará no dia a dia, como remover duplicatas de um array ou criar um contador de frequência.
JavaScript Map
Um Map é uma coleção de pares chave-valor, muito parecido com um object simples — mas com diferenças importantes que o tornam a melhor escolha em muitas situações.
Map vs. object simples: quando usar um Map
Prefira um Map em vez de um object simples quando:
- As chaves não são strings. As chaves de um object são sempre convertidas para strings (ou symbols). Um Map permite usar qualquer valor como chave: objects, funções, números e até
NaN. - Você adiciona e remove entradas com frequência. Maps são otimizados para inserções e exclusões frequentes, e
map.sizefornece a contagem diretamente (objects precisam deObject.keys(obj).length). - Você precisa de ordem de iteração garantida. Um Map sempre itera na ordem de inserção.
- Você quer evitar colisões com o prototype. Um object simples herda chaves como
toStringeconstructor; um Map não possui essas chaves embutidas, portanto chaves fornecidas pelo usuário nunca entrarão em conflito com elas.
Use um object simples quando os dados têm uma estrutura fixa e conhecida (um registro), ou quando você precisa de serialização JSON — JSON.stringify funciona com objects mas não com Maps.
Criando e manipulando Maps
Para criar um Map, use new Map(). Ele suporta os seguintes métodos e propriedades:
map.set(key, value): Adiciona ou atualiza um par chave-valor. Retorna o Map, permitindo encadeamento de chamadas.map.get(key): Obtém o valor de uma chave (undefinedse não existir).map.has(key): Retornatruese a chave existir.map.delete(key): Remove um par chave-valor.map.clear(): Remove tudo.map.size: O número de pares chave-valor.
Como set() retorna o Map, você pode encadear chamadas:
Usando qualquer valor como chave
Ao contrário de objects, um Map mantém as chaves como estão. O número 1 e a string "1" são chaves diferentes, e objects ou funções podem ser chaves (comparados por referência):
Iterando sobre um Map
Um Map itera na ordem de inserção e oferece três métodos de iteração além do forEach:
map.keys()— um iterável de chaves.map.values()— um iterável de valores.map.entries()— um iterável de pares[key, value](este é o padrão, portantofor...of mapfunciona diretamente).map.forEach((value, key) => ...)— executa um callback para cada entrada.
Convertendo entre Map e object
Um Map pode ser construído a partir das entradas de um object e convertido de volta em um:
JavaScript Set
Um Set é uma coleção de valores únicos — cada valor pode aparecer apenas uma vez. Ele é intimamente relacionado a um array, mas sem duplicatas e sem acesso por índice.
Set vs. array: quando usar um Set
Prefira um Set em vez de um array quando:
- A unicidade é importante. Um Set rejeita automaticamente duplicatas, portanto você nunca precisa verificar antes de adicionar.
- Você verifica a presença de elementos com frequência.
set.has(value)é rápido e de leitura clara, enquantoarray.includes(value)percorre todo o array a cada vez.
Use um array quando precisar de acesso por índice, duplicatas ou métodos de array como map/filter/reduce. (Você sempre pode converter entre os dois.)
Trabalhando com Sets
new Set(iterable): Cria um Set, opcionalmente a partir de um array ou qualquer iterável.set.add(value): Adiciona um valor (retorna o Set, permitindo encadeamento). Duplicatas são ignoradas.set.has(value): Retornatruese o valor estiver presente.set.delete(value): Remove um valor.set.size: O número de valores.set.clear(): Remove tudo.
Removendo duplicatas de um array (o uso mais comum)
O motivo mais comum para usar um Set é remover duplicatas de um array. Espalhe o Set de volta em um array com [...new Set(arr)]:
Iterando sobre um Set
Sets iteram na ordem de inserção e suportam for...of e forEach:
União, interseção e diferença
Sets tornam as operações clássicas de conjuntos fáceis. Motores modernos também fornecem os métodos embutidos set.union(), set.intersection() e set.difference(), mas aqui está a abordagem portável usando arrays:
Um cenário real: contador de frequência de palavras
Este exemplo mostra por que um Map frequentemente supera um object simples. Contamos quantas vezes cada palavra aparece em uma frase. Com um Map, as chaves permanecem como valores string reais, size é imediato e não há risco de uma palavra colidir com o nome de uma propriedade herdada:
Tanto Map quanto Set são iteráveis, portanto funcionam com for...of, o operador spread (...) e desestruturação. Além disso, o JavaScript fornece WeakMap e WeakSet, que permitem que suas chaves sejam coletadas pelo garbage collector. Saiba mais em nossa página de JavaScript WeakMap e WeakSet.
Tabela de referência de métodos
Map
| Operação | Código |
|---|---|
| Criar | new Map() ou new Map(Object.entries(obj)) |
| Adicionar / atualizar | map.set(key, value) (encadeável) |
| Ler | map.get(key) |
| Verificar | map.has(key) |
| Remover | map.delete(key) |
| Contar | map.size |
| Iterar | for (let [k, v] of map), map.keys(), map.values(), map.entries(), map.forEach() |
| Para object | Object.fromEntries(map) |
Set
| Operação | Código |
|---|---|
| Criar | new Set() ou new Set(array) |
| Adicionar | set.add(value) (encadeável, ignora duplicatas) |
| Verificar | set.has(value) |
| Remover | set.delete(value) |
| Contar | set.size |
| Iterar | for (let v of set), set.forEach() |
| Remover duplicatas do array | [...new Set(array)] |
Regra geral: use um Map quando precisar de dados indexados com chaves não-string, atualizações frequentes ou ordem garantida; use um Set quando precisar de uma coleção de valores únicos com verificações rápidas de presença. Para todo o resto, objects e arrays simples continuam sendo as ferramentas certas.