Algum ponto em usar o ES6 Map quando chaves são todas strings?

36

Chaves de objetos simples devem ser cadeias de caracteres, enquanto a Mappode ter chaves de qualquer tipo.

Mas tenho pouco uso para isso na prática. Em quase todos os casos, eu me pego usando cadeias de caracteres como chaves de qualquer maneira. E presumivelmente new Map()é mais lento que {}. Portanto, existe alguma outra razão pela qual seria melhor usar um Mapobjeto em vez de um objeto simples?

callum
fonte
3
MDN , como sempre, tem uma boa comparação.
Chris Hayes
11
Para sua informação, o mapa parece ser mais rápido tanto para configuração quanto para obtenção.
MPEN
@mpen - jsperf está fora do ar agora. Você tem certeza de ter map.set('foo', 123)realizado mais rápido que obj.foo = 123? Se assim for isso é muito surpreendente
callum
@ callum Uhh..não, não é positivo. Você pode escrever alguns novos testes de desempenho.
MPEN

Respostas:

42

Existem algumas razões pelas quais prefiro usar Maps sobre objetos simples ( {}) para armazenar dados de tempo de execução (caches, etc):

  1. A .sizepropriedade me informa quantas entradas existem neste mapa;
  2. Os vários métodos de utilidade - .clear(), .forEach(), etc;
  3. Eles me fornecem iteradores por padrão!

Todos os outros casos, como passar argumentos de função, armazenar configurações e etc, são todos escritos usando objetos simples.

Lembre-se também: não tente otimizar seu código muito cedo. Não perca seu tempo fazendo comparações entre o objeto simples e o Maps, a menos que seu projeto esteja sofrendo problemas de desempenho.

gustavohenke
fonte
11
Qual é a função de hashcode de identidade usada pelo Javascript?
Pacerier 18/09/17
11
@Pacerier === :)
gustavohenke
Atualmente, os mapas são muito mais rápidos que objetos simples.
jayarjo
@gustavohenke Isso não é verdade. Mapusa o algoritmo SameValueZero. developer.mozilla.org/pt-BR/docs/Web/JavaScript/…
lolmaus - Andrey Mikhaylov
@ lolmaus-AndreyMikhaylov ok, mas eu disse algo sobre Maps usando isso ou aquilo?
gustavohenke
4

Não tenho certeza disso, mas acho que o desempenho NÃO é um motivo para usar o Maps. Dê uma olhada nesta página jsperf atualizada:

http://jsperf.com/es6-map-vs-object-properties/73

Parece que (ao lidar com seqüências de caracteres, pelo menos) objetos são muito mais rápidos que mapas para configuração e obtenção básicas.

starlogodaniel
fonte
2
Não é assim que você escreve testes de desempenho.
Qix
6
Não é assim que você escreve comentários úteis. Sinta-se à vontade para elaborar se você tem uma metodologia alternativa a sugerir. O que há de errado especificamente com a forma como esses testes foram escritos? Eles são de alguma forma inválidos ou inúteis?
Starlogodaniel 7/08
9
As semânticas / construções de idiomas que estão sendo testadas por meio de marcas de microbench devem diferir apenas em uma variável. Seus testes variam de acordo com o número de iterações, e alguns deles terão o conteúdo do loop interno otimizado, pois o resultado não é utilizado. Alguns testes pré-declaram variáveis, enquanto outros têm a declaração de variável alinhada com o loop for - o que pode resultar em diferentes anormalidades de desempenho.
Qix
11
Ouch, você está absolutamente certo. Em minha defesa, a minha versão foi uma melhoria em relação à versão anterior, mas eu perdi o conteúdo da pré-declaração e o loop interno que estava sendo otimizado. Eu estava trabalhando com um colega que melhorou meu rascunho e acho que resolveu esses problemas: jsperf.com/es6-map-vs-object-properties/88 . No entanto, acho que é válido ter estilos de loop diferentes para as diferentes estruturas de dados; em uso real, as pessoas escolherão a estrutura de loop com o melhor desempenho, e Map e Object terão diferentes estruturas de loop "ideais". De qualquer forma, obrigado pela captura.
starlogodaniel
Ok, entendo agora - eles costumavam ser mais lentos do que objetos simples, mas foram fortemente otimizados em navegadores recentes.
jayarjo
0

As outras respostas não mencionam uma última diferença entre objetos Mapes:

O Mapobjeto contém pares de valores-chave e lembra a ordem de inserção original das chaves .

Assim, ao iterar sobre ele, um objeto Map retorna chaves em ordem de inserção.

Citação de MDN , ênfase minha


Essa foi a principal razão pela qual decidi usar Mappela primeira vez em um projeto recente. Eu tinha um objeto normal que precisava exibir em um <table>, com cada propriedade em uma linha específica.

let productPropertyOrder = [ "name", "weight", "price", "stocked" ];

let product =
{
    name: "Lasagne",
    weight: "1kg",
    price: 10,
    stocked: true
}

Eu escrevi uma função para transformar um objeto em um Map acordo com uma ordem de chave desejada:

function objectToMap( obj, order )
{
    let map = new Map();

    for ( const key of order )
    {
        if ( obj.hasOwnProperty( key ) )
        {
            map.set( key, obj[ key ] );
        }
    }

    return map;
}

Em seguida, o mapa pode ser iterado na ordem desejada:

let productMap = objectToMap( product, productPropertyOrder );

for ( const value of productMap.values() )
{
    let cell = document.createElement( "td" );
    cell.innerText = value;
    row.appendChild( cell );
}

É claro que isso é um pouco artificial, porque é possível exibir ao iterar a ordem da propriedade sem criar um Mapno processo:

for ( const key of productPropertyOrder )
{
    if ( product.hasOwnProperty( key ) )
    {
        let value = product[ key ];
        // create cell
    }
}

Mas se você tem uma variedade desses objetos e os exibe em muitos lugares, primeiro faz sentido convertê-los em mapas.

WD40
fonte