Подтвердить что ты не робот

Как преобразовать простой объект в карту ES6?

По какой-то причине я не могу найти эту простую вещь в документах MDN (возможно, я просто пропустил ее).

Я ожидал, что это сработает:

const map = new Map({foo: 'bar'});

map.get('foo'); // 'bar'

... но первая строка выбрасывает TypeError: (var)[Symbol.iterator] is not a function

Как создать карту из простого объекта? Должен ли я сначала преобразовать его в массив массивов пар ключ-значение?

4b9b3361

Ответ 1

Для инициализации Map вы можете использовать любой итератор, который возвращает пары ключ/значение в виде массивов, например массив массивов:

const map = new Map([
    ['foo', 'bar']
]);

Нет никакого встроенного преобразования от объекта к карте, но это легко сделать с помощью Object.keys:

const map = new Map();
let obj = {foo: 'bar'};
Object.keys(obj).forEach(key => {
    map.set(key, obj[key]);
});

Вы можете, конечно, дать себе рабочую функцию для обработки этого:

function buildMap(obj) {
    let map = new Map();
    Object.keys(obj).forEach(key => {
        map.set(key, obj[key]);
    });
    return map;
}

Тогда

const map = buildMap({foo: 'bar'});

Или здесь более l33t-выглядящий (это что-то еще?) версия:

function buildMap(obj) {
    return Object.keys(obj).reduce((map, key) => map.set(key, obj[key]), new Map());
}

(Да, Map#set возвращает ссылку на карту. Некоторые утверждают, что это злоупотребление reduce.)

Или мы действительно можем пережить верх над неизвестностью:

const buildMap = o => Object.keys(o).reduce((m, k) => m.set(k, o[k]), new Map());

Нет, я бы никогда не сделал этого по-настоящему.: -)

Ответ 2

Да, конструктор Map принимает массив пар ключ-значение.

Существует предложение ES Stage4 для Object.entries, которое возвращает массив значений ключа для объекта:

const map = new Map(Object.entries({foo: 'bar'}));

map.get('foo'); // 'bar'

В настоящее время он реализован в Firefox 46+ и Edge 14+ (и за флагом в Chrome).

Если транспиляция не является для вас вариантом, посмотрите на ответ TJ Crowder или используйте polyfill, например, рекомендованный georg:

Object.entries = typeof Object.entries === 'function' ? Object.entries : obj => Object.keys(obj).map(k => [k, obj[k]]);

Обновление 19.09.2017: оно в ES2017

Как упоминалось в комментариях AnilRedshift, Object.entries теперь является частью окончательной спецификации ES2017 (19.1.2.5).

Ответ 3

Нужно ли мне сначала преобразовать его в массив массивов пар ключ-значение?

Нет, достаточно итератора пар ключей-значений. Вы можете использовать следующее, чтобы избежать создания промежуточного массива:

function* entries(obj) {
    for (let key in obj)
        yield [key, obj[key]];
}

const map = new Map(entries({foo: 'bar'}));
map.get('foo'); // 'bar'

Ответ 4

const myMap = new Map(
    Object
        .keys(myObj)
        .map(
            key => [key, myObj[key]]
        )
)

Ответ 5

В качестве альтернативы вы можете использовать метод lodash toPairs:

const _ = require('lodash');
const map = new Map(_.toPairs({foo: 'bar'}));