Функция map для объектов (вместо массивов)
У меня есть объект:
myObject = { 'a': 1, 'b': 2, 'c': 3 }
Я ищу нативный метод, аналогичный Array.prototype.map
, который можно было бы использовать следующим образом:
newObject = myObject.map(function (value, label) {
return value * value;
});
// Теперь newObject равен { 'a': 1, 'b': 4, 'c': 9 }
Существует ли в JavaScript такая функция map
для объектов? (Мне нужно это для Node.JS, поэтому проблемы с кроссбраузерностью меня не интересуют.)
5 ответ(ов)
Это довольно просто написать свою версию функции map
для объектов:
Object.map = function(o, f, ctx) {
ctx = ctx || this;
var result = {};
Object.keys(o).forEach(function(k) {
result[k] = f.call(ctx, o[k], k, o);
});
return result;
}
Вот пример использования:
> o = { a: 1, b: 2, c: 3 };
> r = Object.map(o, function(v, k, o) {
return v * v;
});
> r
{ a: 1, b: 4, c: 9 }
Обратите внимание, что эта версия также позволяет (по желанию) установить контекст this
для коллбэка, как и метод для массивов.
ПРАВКА - Изменено так, чтобы не использовать Object.prototype
, чтобы избежать конфликта с возможным существующим свойством с именем map
в объекте.
Это действительно раздражает, и все в сообществе JavaScript это знают. Такая функциональность должна существовать:
const obj1 = {a: 4, b: 7};
const obj2 = Object.map(obj1, (k, v) => v + 5);
console.log(obj1); // {a: 4, b: 7}
console.log(obj2); // {a: 9, b: 12}
Вот наивная реализация:
Object.defineProperty(Object, 'map', {
value: function(obj, fn, ctx) {
const ret = {};
for (let k of Object.keys(obj)) {
ret[k] = fn.call(ctx || null, k, obj[k]);
}
return ret;
},
enumerable: false
});
Это крайне неудобно всё время реализовывать это самостоятельно 😉
Если вы хотите что-то немного более изощренное, что не будет вмешиваться в класс Object, попробуйте вот это:
const map = function (obj, fn, ctx) {
return Object.keys(obj).reduce((a, b) => {
a[b] = fn.call(ctx || null, b, obj[b]);
return a;
}, {});
};
const x = map({a: 2, b: 4}, (k, v) => {
return v * 2;
});
Безопасно добавлять эту функцию map
к Object
; будьте осторожны, чтобы не назначать напрямую Object.prototype
- если вы хотите расширить прототип, используйте Object.defineProperty
с enumerable: false
.
// довольно безопасно:
Object.map = ...
// не рекомендуется (вызывает наличие свойства "map" у всех объектов):
Object.prototype.map ...
// довольно безопасно:
Object.defineProperty(Object.prototype, 'map', { value: ..., enumerable: false });
Минимальная версия
ES2017
Object.entries(obj).reduce((a, [k, v]) => (a[k] = v * v, a), {})
↑↑↑↑↑
В этой версии используется Object.entries()
для получения массива пар [ключ, значение] из объекта. Затем, с помощью метода reduce()
, мы создаем новый объект, где значения возводятся в квадрат.
ES2019
Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, v * v]))
↑↑↑↑↑
В данном случае мы также начинаем с `
Я пришёл сюда в поисках ответа на вопрос о том, как преобразовать объект в массив, и нашёл эту страницу. Если вы ищете тот же ответ, который искал я, вот как можно преобразовать объект в массив.
Вы можете использовать метод map
, чтобы вернуть новый массив из объекта следующим образом:
var newObject = Object.keys(myObject).map(function(key) {
return myObject[key];
});
Этот код создаёт массив, содержащий значения объекта myObject
.
Для достижения максимальной производительности.
Если ваш объект не меняется часто, но требуется его частая итерация, я рекомендую использовать нативный Map в качестве кеша.
// пример объекта
var obj = {a: 1, b: 2, c: 'something'};
// кеширующий Map
var objMap = new Map(Object.entries(obj));
// быстрая итерация по объекту Map
objMap.forEach((item, key) => {
// выполнить что-то с элементом
console.log(key, item);
});
Object.entries уже поддерживается в Chrome, Edge, Firefox и бета-версии Opera, поэтому это перспективная функция. Она была введена в ES7, так что для IE, где она не работает, можно использовать полифилл: https://github.com/es-shims/Object.entries.
Использование async/await с циклом forEach
Запись в файлы в Node.js
Как получить полный объект в console.log() Node.js, а не '[Object]'?
Как вывести циклическую структуру в формате, похожем на JSON?
Как прочитать JSON-файл в память сервера?