Будь-який сенс використання ES6 Map, коли клавішами є всі рядки?


36

Прості клавіші об'єкта повинні бути рядками, тоді як у Mapклавіші "може бути" будь-якого типу.

Але я мало корисний для цього на практиці. Майже у всіх випадках я все одно користуюся рядками як клавішами. І, мабуть new Map(), повільніше, ніж {}. То чи є якась інша причина, чому може бути краще використовувати Mapзамість простого об'єкта?


3
MDN , як завжди, має гарне порівняння.
Кріс Хейс

1
FYI, карта здається швидшою як для налаштування, так і для отримання.
квітня 1616

@mpen - jsperf зараз не працює. Ви впевнені, що працюєте map.set('foo', 123)швидше obj.foo = 123? Якщо так, це дуже дивно
callum

@callum Uhh..но, не позитивно. Ви можете написати нові тести на ефективність.
mpen

Відповіді:


42

Є деякі причини, чому я вважаю за краще використовувати Maps над простими об'єктами ( {}) для зберігання даних часу виконання (кеші тощо):

  1. .sizeВластивість дозволяє мені знати , скільки існують записи в цій карті;
  2. Різні методи корисності - .clear(), .forEach()і т.д .;
  3. Вони надають мені ітератори за замовчуванням!

У кожному іншому випадку, як передача аргументів функції, зберігання конфігурацій та ін., Всі записуються за допомогою простих об'єктів.

Також пам’ятайте: не намагайтеся оптимізувати код занадто рано. Не витрачайте час на тестування простого об’єкта та карт, якщо ваш проект не має проблем із ефективністю.


1
Яку функцію хеш-коду особи використовує Javascript?
Pacerier

1
@Pacerier ===:)
gustavohenke

Карти в наші дні набагато швидші, ніж звичайні об'єкти.
jayarjo

@gustavohenke Це неправда. Mapвикористовує алгоритм SameValueZero. developer.mozilla.org/en-US/docs/Web/JavaScript/…
lolmaus - Андрій Михайлов

@ lolmaus-AndreyMikhaylov добре, але я щось сказав про Mapвикористання цього чи іншого?
gustavohenke

4

Я не впевнений у цьому, але думаю, що ефективність НЕ є приводом для використання Карт. Подивіться на цю оновлену сторінку jsperf:

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

Схоже, що (при роботі хоча б з рядками) об'єкти набагато швидше, ніж карти для базового налаштування та отримання.


2
Це не те, як ви пишете тести на продуктивність.
Qix

6
Це не те, як ви пишете корисні коментарі. Будь ласка, не соромтеся розробити, якщо у вас є альтернативна методологія, яку можна запропонувати. Що конкретно не так у тому, як були написані ці тести? Вони якимось чином недійсні чи недобросовісні?
starlogodaniel

9
Мовна семантика / конструкції, які тестуються за допомогою мікробірок, повинні відрізнятися лише однією змінною. Ваші тести різняться за кількістю ітерацій, і для деяких з них буде оптимізовано вміст внутрішнього циклу, оскільки результат не використовується. Деякі тести попередньо оголошують змінні, а інші мають декларацію змінної в рядку з циклом for - що може спричинити різні порушення продуктивності.
Qix

1
О, ти абсолютно прав. На мій захист моя версія була вдосконаленням тієї, що була до неї, але я пропустив оптимізацію як попереднього оголошення, так і змісту внутрішнього циклу. Я працював з колегою, яка покращила проект, і я думаю, що це вирішило: jsperf.com/es6-map-vs-object-properties/88 . Однак я думаю, що справедливо мати різні стилі циклу для різних структур даних; в реальному використанні люди виберуть циклічну структуру з найкращою продуктивністю, а Map and Object мають різні "оптимальні" структури циклу. У будь-якому випадку, дякую за улов.
starlogodaniel

Гаразд, я бачу зараз - вони були повільнішими, ніж звичайні об'єкти, але були значно оптимізовані в останніх браузерах.
jayarjo

0

В інших відповідях не згадується остання різниця між об'єктами та Maps:

MapОб'єкт містить пари ключ-значення , і запам'ятовує вихідний порядок введення ключів .

Таким чином, під час ітерації над ним об’єкт Map повертає ключі в порядку вставки.

Цитата з MDN , моє наголос


Це було основною причиною, яку я вирішив 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
    }
}

Але якщо у вас є масив таких об’єктів і ви збираєтесь відображати їх багато місць, то перетворення їх усіх на карти спочатку має сенс.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.