Mapas vs Objetos no ES6, quando usar?

83

Ref: Mapas MDN

Use mapas sobre objetos quando as chaves forem desconhecidas até o tempo de execução e quando todas as chaves forem do mesmo tipo e todos os valores forem do mesmo tipo.

Use objetos quando houver lógica que opera em elementos individuais.

Questão:

Qual é um exemplo aplicável de uso de mapas sobre objetos? em particular, "quando as chaves seriam desconhecidas até o tempo de execução?"

var myMap = new Map();

var keyObj = {},
    keyFunc = function () { return 'hey'},
    keyString = "a string";

// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

console.log(myMap.get(keyFunc));
Matthew Harwood
fonte
Sim, eu percebi isso. Como eu defino uma função como um valor. @JonathanLonowski você pode pensar em quando eu deveria fazer isso :( é difícil pensar em casos de uso.
Matthew Harwood
7
Você pode usá-lo onde quer dizer um elemento DOM que deseja associar alguns dados ao uso de um objeto. Em vez de usar, digamos, o ID do elemento como a chave em um objeto, você pode usar o próprio elemento como uma chave em um Mapa para que não se importe se o elemento tem um ID (ou qualquer outro identificador único que não seja uma referência de objeto ) ou não.
RobG de
1
@RobG é apenas uma pequena adição: nesse caso, é um WeakMapque também pode ser útil.
zerkms
1
Acho que isso sugere o uso de objetos como / para registros e mapas para todos os outros tipos de mapeamento. Com registros, quero dizer uma estrutura de dados com um conjunto fixo de campos, como um objeto de usuário que possui os campos namee, idpor exemplo.
Felix Kling
1
Quando eu estava lendo aquela página MDN, a lista de marcadores de casos de uso foi muito mais útil do que o parágrafo que você citou. Certamente em relação à questão colocada em seu título.
CodingIntrigue

Respostas:

51

Qual é um exemplo aplicável de uso de mapas sobre objetos?

Acho que você já deu um bom exemplo: você pelo menos precisa usar Maps quando estiver usando objetos (incluindo objetos Function) como chaves.

em particular, "quando as chaves seriam desconhecidas até o tempo de execução?"

Sempre que não forem conhecidos em tempo de compilação. Resumindo, você sempre deve usar um Mapquando precisar de uma coleção de valores-chave . Um bom indicador de que você precisa de uma coleção é quando você adiciona e remove valores dinamicamente da coleção, e especialmente quando você não conhece esses valores de antemão (por exemplo, eles são lidos de um banco de dados, inseridos pelo usuário, etc).

Em contraste, você deve usar objetos quando sabe quais e quantas propriedades o objeto tem enquanto escreve o código - quando sua forma é estática. Como @Felix colocou: quando você precisar de um registro . Um bom indicador para isso é quando os campos têm tipos diferentes e quando você nunca precisa usar a notação de colchetes (ou esperar um conjunto limitado de nomes de propriedades nela).

Bergi
fonte
1
Ou de outro ponto de vista: Sempre que você precisar iterar sobre as propriedades do seu objeto no nível de dados (por exemplo for..of) em vez de no nível do programa (por exemplo for..in), use a Map. Mais informações sobre estes termos nesta resposta .
Adicionarei como comentário também o fato de que sempre que você não souber que tipo de chave será sua chave e não esperar string como tipos de dados de chave, use map stackoverflow.com/questions/32600157/…
Carmine Tambascia
26

Eu acho que com o ES2015 Mapapenas duas razões são deixadas para usar objetos simples:

Quando a ordem de propriedade não é importante?

  • se você tiver apenas um único valor e algumas funções que devem ser associadas explicitamente a ele (como Promise- que é um proxy para um valor futuro - e then/ catch)
  • se você tiver uma estrutura de dados tipo struct / registro com um conjunto estático de propriedades conhecido em "tempo de compilação" (geralmente structs / records não são iteráveis)

Em todos os outros casos, você pode considerar o uso Map, porque preserva a ordem das propriedades e separa o programa (todas as propriedades atribuídas ao Mapobjeto) do nível de dados (todas as entradas no Mappróprio).

Quais são as desvantagens de Map?

  • você perde a sintaxe literal concisa do objeto
  • você precisa de substitutos personalizados para JSON.stringyfy
  • você perde a desestruturação, o que é mais útil com estruturas de dados estáticos de qualquer maneira

fonte
Essa linha me preocupa muito: "provavelmente é mais lento do que objetos puros, semelhantes a hashmap". Pensei em substituir todos os meus objetos por mapas devido a melhorias de desempenho. Mas você diz que é mais lento ...
mesqueeb
1
Você está certo. Mapé provavelmente mais rápido, porque é baseado puramente em um hash, enquanto Objecté um pouco mais complicado. Obrigado!
11

Use mapas sobre objetos quando as chaves forem desconhecidas até o tempo de execução e quando todas as chaves forem do mesmo tipo e todos os valores forem do mesmo tipo.

Não tenho ideia de por que alguém escreveria algo tão obviamente errado. Devo dizer que as pessoas estão encontrando cada vez mais conteúdo errado e / ou questionável no MDN atualmente.

Nada nessa frase está correto. O principal motivo para usar mapas é quando você deseja chaves com valor de objeto. A ideia de que os valores devam ser do mesmo tipo é absurda - embora possam ser, é claro. A ideia de que não se deve usar objetos quando as chaves são desconhecidas até o tempo de execução é igualmente absurda.


fonte
1
Não vejo o que há de tão absurdo nessa ideia? Quando você precisa de coleções, elas são tipicamente digitadas estritamente (pode haver exceções, é claro). Além disso, acho que deixar de usar objetos para coleções (quando Mapdisponível) é um bom conselho.
Bergi
Para que as coleções sejam tipicamente estritamente digitadas, é logicamente distinto de dizer que algo estritamente digitado deve ser uma coleção.
1
Sim, acho que é um pouco estranho, mas a ideia é boa. Eu acho que eles pensaram que "as chaves são desconhecidas até o tempo de execução" já faz uma coleção. Alguma ideia para um melhor fraseado?
Bergi,
1
Acordado. O MDN tem uma documentação muito boa, mas eles devem se limitar a documentar a documentação das APIs e não tentar fornecer conselhos de programação.
AlexG
5

Uma das diferenças entre Mape Objecté:

Mappode usar tipos de dados complexos como sua chave. como isso:

const fn = function() {}
const m = new Map([[document.body, 'stackoverflow'], [fn, 'redis']]);

m.get(document.body) // 'stackoverflow'
m.get(fn) //'redis'

cuidado: Para tipos de dados complexos, se você deseja obter o valor, deve passar a mesma referência da chave.

Object, ele aceita apenas o tipo de dados simples ( number, string) como sua chave.

const a = {};
a[document.body] = 'stackoverflow';

console.log(a) //{[object HTMLBodyElement]: "stackoverflow"}
slideshowp2
fonte
2

Esta pergunta é uma duplicata de mas até que seja fechado, aqui está minha resposta de lá :

Além das outras respostas, descobri que a operação com mapas é mais complicada e prolixa do que com objetos.

obj[key] += x
// vs.
map.set(map.get(key) + x)

Isso é importante porque um código mais curto é mais rápido de ler, mais diretamente expressivo e melhor guardado na cabeça do programador .

Outro aspecto: como set () retorna o mapa, não o valor, é impossível encadear as atribuições.

foo = obj[key] = x;  // Does what you expect
foo = map.set(key, x)  // foo !== x; foo === map

Depurar mapas também é mais doloroso. Abaixo, você não pode realmente ver quais chaves estão no mapa. Você teria que escrever um código para fazer isso.

Boa sorte avaliando um Map Iterator

Os objetos podem ser avaliados por qualquer IDE:

WebStorm avaliando um objeto

Dan Dascalescu
fonte
6
Isso não responde à pergunta " Qual é um exemplo aplicável de uso de mapas sobre objetos? " De forma alguma
Bergi
6
Por favor, não publique suas respostas. E não, a pergunta não é uma duplicata.
Bergi
1

Objects são semelhantes a Maps no sentido de que ambos permitem definir chaves para valores, recuperar esses valores, excluir chaves e detectar se algo está armazenado em uma chave. Por causa disso (e porque não havia alternativas integradas), Objects têm sido usados ​​como Maps historicamente; no entanto, existem diferenças importantes que tornam o uso de um Mappreferível em certos casos:

  • As chaves de an Objectsão Strings e Symbols, enquanto podem ser qualquer valor para a Map, incluindo funções, objetos e qualquer primitivo.
  • As chaves Mapsão ordenadas, enquanto as chaves adicionadas ao objeto não. Assim, ao iterar sobre ele, um Mapobjeto retorna chaves na ordem de inserção.
  • Você pode obter o tamanho de um Mapfacilmente com a sizepropriedade, enquanto o número de propriedades em um Objectdeve ser determinado manualmente.
  • A Mapé iterável e, portanto, pode ser iterado diretamente, ao passo que iterar sobre um Objectrequer a obtenção de suas chaves de alguma forma e a iteração sobre elas.
  • Um Objecttem um protótipo, portanto, há chaves padrão no mapa que podem colidir com suas chaves se você não tomar cuidado. No ES5, isso pode ser contornado usando map = Object.create(null), mas raramente é feito.
  • A Mappode ter um desempenho melhor em cenários que envolvem adição e remoção freqüentes de pares de chaves.

MDN

codejockie
fonte