Back

Qual é a Diferença Entre Map, Set e Object em JavaScript?

Qual é a Diferença Entre Map, Set e Object em JavaScript?

Você está refatorando um componente e precisa armazenar pares chave-valor. Por hábito, você recorre a um object, mas hesita. Isso deveria ser um Map? Um Set funcionaria melhor aqui? Esta decisão importa mais do que parece—cada estrutura possui características de desempenho distintas e significado semântico que afetam a clareza e eficiência do seu código.

Esta comparação de estruturas de dados JavaScript detalha as diferenças práticas entre Map, Set e Object para que você possa fazer a escolha certa em código de produção.

Principais Conclusões

  • Objects convertem chaves para strings, enquanto Maps preservam os tipos de chave exatamente—essa distinção previne bugs sutis de colisão.
  • Maps superam Objects em adições e exclusões frequentes, enquanto Objects se destacam em cargas de trabalho com muitas leituras e estruturas estáveis.
  • Sets fornecem verificações de pertencimento O(1) e agora incluem métodos nativos union, intersection e difference no JavaScript moderno.
  • Use Objects por padrão para dados estruturados, recorra a Maps quando as chaves forem dinâmicas ou não-string, e use Sets quando a unicidade for sua principal preocupação.

Propósito Central: Quando Usar Map vs Set vs Object

A diferença entre Map e Object em JavaScript se resume à intenção e ao tratamento de chaves:

  • Object: Dados estruturados com chaves string/symbol conhecidas. Pense em configurações, props de componentes, respostas de API.
  • Map: Coleções dinâmicas de chave-valor onde as chaves podem ser de qualquer tipo. Pense em caches, tabelas de consulta com chaves de objeto, adições e exclusões frequentes.
  • Set: Coleções de valores únicos sem chaves. Pense em deduplicação, rastreamento de itens vistos, verificações de pertencimento.

Tratamento de Chaves: A Diferença Fundamental Entre Map e Object

Objects convertem chaves para strings. Maps preservam os tipos de chave exatamente.

const obj = {}
obj[1] = 'number'
obj['1'] = 'string'
console.log(Object.keys(obj)) // ['1'] — colisão

const map = new Map()
map.set(1, 'number')
map.set('1', 'string')
console.log(map.size) // 2 — chaves distintas

Maps também aceitam objetos como chaves—algo que objects fundamentalmente não podem fazer sem soluções alternativas de serialização.

const userCache = new Map()
const user = { id: 42 }
userCache.set(user, { lastSeen: Date.now() })

Consulte a documentação MDN para Map para semântica completa de chaves.

Semântica de Iteração e Ordenação

Todas as três estruturas possuem ordem de iteração definida, mas a semântica difere:

Map e Set: Ordem pura de inserção. Sempre.

Object: Ordem de inserção para chaves string, mas chaves indexadas por inteiros (por exemplo, '1', '42') são ordenadas numericamente primeiro. Isso pega desenvolvedores desprevenidos:

const obj = { b: 1, 2: 2, a: 3, 1: 4 }
console.log(Object.keys(obj)) // ['1', '2', 'b', 'a']

Maps e Sets são diretamente iteráveis com for...of. Objects requerem Object.keys(), Object.values() ou Object.entries().

Características de Desempenho em Escala

Para a questão de desempenho JavaScript Map vs Set vs Object, o contexto importa:

Objects se destacam em cargas de trabalho com muitas leituras e chaves string. Engines modernas como V8 otimizam o acesso a propriedades através de classes ocultas, tornando as leituras muito rápidas—quando a forma do objeto permanece estável.

Maps vencem em adições e exclusões frequentes. A exclusão de propriedades de objetos (via delete) pode desencadear desotimização ao invalidar classes ocultas. A especificação ECMAScript garante tempo de acesso médio sublinear para Maps, sem exigir uma implementação interna específica.

Sets fornecem verificações de pertencimento O(1) via has(), superando o includes() de arrays para qualquer tamanho de coleção não trivial.

Operações Nativas de Set

Set agora inclui métodos integrados para operações comuns (consulte a documentação MDN para Set):

const a = new Set([1, 2, 3])
const b = new Set([2, 3, 4])

a.union(b)               // Set {1, 2, 3, 4}
a.intersection(b)        // Set {2, 3}
a.difference(b)          // Set {1}
a.symmetricDifference(b) // Set {1, 4}
a.isSubsetOf(b)          // false

Esses métodos são amplamente suportados em navegadores modernos.

Cenários Práticos de Frontend

Use Object quando:

  • Definir props de componentes ou configuração
  • Trabalhar com serialização JSON (Maps não serializam diretamente)
  • As chaves são conhecidas no momento da escrita

Use Map quando:

  • As chaves são dinâmicas ou fornecidas pelo usuário (evita poluição de protótipo)
  • Você precisa de referências de objetos como chaves
  • O rastreamento de tamanho importa (map.size vs Object.keys(obj).length)
  • Construir caches com atualizações frequentes

Use Set quando:

  • Rastrear IDs únicos ou itens vistos
  • Deduplicar arrays: [...new Set(array)]
  • Testes rápidos de pertencimento

Referência Rápida

CaracterísticaObjectMapSet
Tipos de chavestring, symbolanyN/A (apenas valores)
TamanhoObject.keys().length.size.size
Iteraçãoindiretadiretadireta
Suporte JSONnativomanualmanual
Risco de protótiposimnãonão

Conclusão

A escolha entre Map, Set e Object não é sobre qual é “melhor”—é sobre combinar a estrutura de dados ao seu caso de uso. Objects permanecem a escolha certa para dados estruturados com chaves string. Maps lidam com cenários dinâmicos de chave-valor de forma limpa. Sets resolvem problemas de unicidade eficientemente.

Use objects por padrão para simplicidade. Recorra a Map quando precisar de suas capacidades específicas. Use Set quando a unicidade for sua principal preocupação.

Perguntas Frequentes

Não diretamente. JSON.stringify não lida com Maps nativamente. Você precisa converter o Map para um array de entradas primeiro usando Array.from(map) ou o operador spread, e então serializar esse array. Para restaurá-lo, analise o JSON e passe o array resultante para o construtor Map: new Map(JSON.parse(jsonString)).

Maps lidam com inserções e exclusões frequentes sem a desotimização que a exclusão de propriedades de objetos pode causar. Eles também rastreiam o tamanho nativamente com a propriedade size, aceitam qualquer tipo de valor como chave incluindo nós DOM ou referências de objetos, e não apresentam risco de poluição de protótipo de chaves fornecidas pelo usuário.

Esses métodos agora são amplamente suportados em navegadores modernos. Se você precisar suportar ambientes mais antigos, verifique as tabelas de compatibilidade ou use um polyfill.

Use um array quando a ordem de inserção com duplicatas importar, quando você precisar de acesso baseado em índice, ou quando a coleção for pequena o suficiente para que o overhead de um Set não se justifique. Para coleções maiores onde unicidade e buscas rápidas são prioridades, um Set é a melhor escolha.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay