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


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

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

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

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

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

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

7 63

7 ответов:

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

Object.entries Это новый статический метод объекта, доступный в ES2017 (19.1.2.5).

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

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

в настоящее время он реализован в Firefox 46+ и Edge 14+ и более новых версиях Chrome

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

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

см. ответ Нильса с помощью Object.entries и/или ответ Берги с помощью функции генератора. хотя Object.entries еще не было в спецификации, когда был задан вопрос, это было на стадии 4, так безопасно для заполнения и использования даже в апреле 2016 года (просто). (Подробнее о сценах здесь.) И функции генератора были в ES2015. ОП специально попросила избегать посредников, а пока генератор не работает полностью избегайте этого, он делает лучшую работу, чем ниже или (немного)Object.enties.

FWIW, используя Object.entries:

  • создает массив [name, value] массивы для передачи в new Map
  • The Map конструктор вызывает функцию в массиве для получения итератора; массив создает и возвращает объект interator массива.
  • The Map конструктор использует этот объект итератора для получения записей ([name, value] массивы) и построить карта

С помощью генератора:

  • создает объект генератора в результате вызова функции генератора
  • The Map конструктор вызывает функцию на этом объекте генератора, чтобы получить итератор от него; объект генератора возвращает
  • The Map конструктор использует объект генератора (как итератор) для получения записей ([name, value] массивы) и построить карта

Итак: одним посредником меньше (массив из Object.entries).

, используя Object.entries проще и создание этого массива не является проблемой 99,999% времени. Так что на самом деле, либо один. Но они оба лучше, чем ниже. : -)

оригинальный ответ:

для инициализации a 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-looking (это все еще вещь?) версия:

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

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

или действительно go над-верхом на безвестности:

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

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

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

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

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

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

ответ от Nils описание как для преобразования объектов в карты, которые я нашел очень полезным. Однако ОП также задавался вопросом, где эта информация находится в документах MDN. Хотя он, возможно, не был там, когда вопрос был первоначально задан, теперь он находится на странице MDN для

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

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

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

С помощью некоторого JQuery,

const myMap = new Map();
$.each( obj, function( key, value ) {
myMap[key] = value;
});