Как преобразовать обычный объект в карту ES6?
по какой-то причине я не могу найти эту простую вещь в MDN docs (может быть, я просто пропустил его).
Я ожидал, что это сработает:
const map = new Map({foo: 'bar'});
map.get('foo'); // 'bar'
...но первая строка бросает TypeError: (var)[Symbol.iterator] is not a function
Как сделать карту из простого объекта? Мне действительно нужно сначала преобразовать его в массив пар ключ-значение?
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 для
в качестве альтернативы вы можете использовать lodash toPairs способ:
const _ = require('lodash'); const map = new Map(_.toPairs({foo: 'bar'}));