Есть ли смысл использовать ES6 Map, когда все ключи являются строками?

36

Ключи простого объекта должны быть строками, а Mapключи могут иметь ключи любого типа.

Но я практически не пользуюсь этим на практике. В любом случае я почти всегда использую строки в качестве ключей. И, вероятно new Map(), медленнее, чем {}. Так есть ли какая-то другая причина, почему может быть лучше использовать Mapвместо простого объекта?

Каллум
источник
3
MDN , как обычно, имеет хорошее сравнение.
Крис Хейс
1
К вашему сведению, карта, кажется, быстрее для установки и получения.
mpen
@mpen - jsperf сейчас недоступен. Вы уверены, что map.set('foo', 123)выступили быстрее, чем obj.foo = 123? Если это так, это очень удивительно
каллум
@callum Э-э-э, нет, не позитивно. Возможно, вы захотите написать несколько новых тестов производительности.
mpen

Ответы:

42

Есть несколько причин, по которым я предпочитаю использовать Maps вместо простых объектов ( {}) для хранения данных времени выполнения (кэши и т. Д.):

  1. .sizeСвойство позволяет мне знать , сколько существуют записи в этой карте;
  2. Различные методы полезности - .clear(), .forEach()и т.д.;
  3. Они предоставляют мне итераторы по умолчанию!

Все остальные случаи, такие как передача аргументов функций, хранение конфигураций и т. Д., Все пишутся с использованием простых объектов.

Также помните: не пытайтесь оптимизировать свой код слишком рано. Не тратьте свое время на тестирование простого объекта по сравнению с Картами, если ваш проект не испытывает проблем с производительностью.

gustavohenke
источник
1
Какая функция хэш-кода идентичности используется Javascript?
Pacerier
1
@Pacerier ===:)
густавохенке
Карты намного быстрее, чем простые объекты в наши дни.
Джаярджо
@ Gustavohenke Это не правда. Mapиспользует алгоритм SameValueZero. developer.mozilla.org/en-US/docs/Web/JavaScript/…
lolmaus - Андрей Михайлов
@ lolmaus-AndreyMikhaylov хорошо, но я что-то говорил о том, чтобы Mapиспользовать то или это?
Густавохенке
4

Я не уверен в этом, но я думаю, что производительность НЕ является причиной для использования Карт. Взгляните на эту обновленную страницу jsperf:

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

Похоже (по крайней мере, при работе со строками) объекты намного быстрее, чем карты для базовой установки и получения.

starlogodaniel
источник
2
Это не то, как вы пишете тесты производительности.
Qix
6
Это не то, как вы пишете полезные комментарии. Пожалуйста, не стесняйтесь уточнять, если у вас есть альтернативная методология, чтобы предложить. Что конкретно не так с тем, как были написаны эти тесты? Являются ли они каким-либо образом недействительными или бесполезными?
Старлогоданиель
9
Языковая семантика / конструкции, тестируемые с помощью микробенчмарков, должны отличаться только одной переменной. Ваши тесты варьируются в зависимости от количества итераций, и у некоторых из них будет оптимизировано содержимое их внутреннего цикла, поскольку результат не используется. Некоторые тесты предварительно объявляют переменные, в то время как другие имеют объявление переменных, встроенное в цикл for, что может привести к различным отклонениям производительности.
Qix
1
Ой, ты абсолютно прав. В мою защиту, моя версия была улучшением предыдущей, но я пропустил предварительное объявление и оптимизацию содержимого внутреннего цикла. Я работал с коллегой, который улучшил мой проект, и я думаю, что решил эти проблемы: jsperf.com/es6-map-vs-object-properties/88 . Однако я думаю, что допустимо иметь разные стили цикла для разных структур данных; при реальном использовании люди будут выбирать структуру цикла с наилучшей производительностью, а у Map и Object будут разные «оптимальные» структуры цикла. В любом случае, спасибо за улов.
Старлогоданиель
Хорошо, теперь я вижу - они раньше были медленнее, чем простые объекты, но были сильно оптимизированы в последних браузерах.
Джаярджо
0

Другие ответы не упоминают одно последнее различие между объектами и Maps:

MapОбъект содержит пары ключ-значение , и запоминает исходный порядок ввода ключей .

Таким образом, при итерации по нему объект Map возвращает ключи в порядке вставки.

Цитата из МДН , акцент мой


Это было главной причиной, которую я решил использовать Mapвпервые в недавнем проекте. У меня был нормальный объект, который мне нужно было отобразить в a <table>, причем каждое свойство находилось в определенной строке.

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

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

Я написал функцию для преобразования объекта в Mapсоответствии с желаемым порядком клавиш:

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

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

    return map;
}

Затем карта может быть перебрана в желаемом порядке:

let productMap = objectToMap( product, productPropertyOrder );

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

Конечно, это немного надумано, так как можно было бы отображать итерацию по порядку свойств без создания Mapв процессе:

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

Но если у вас есть массив таких объектов и вы собираетесь отображать их во многих местах, то сначала имеет смысл преобразовать их все в карты.

WD40
источник