I have an object:
myObject = { 'a': 1, 'b': 2, 'c': 3 }
I am looking for a native method, similar to Array.prototype.map that would be used as follows:
newObject = myObject.map(function (value, label) {
return value * value;
});
// newObject is now { 'a': 1, 'b': 4, 'c': 9 }
Does JavaScript have such a map function for objects? (I want this for Node.JS, so I don't care about cross-browser issues.)
39 Answers
There is no native map to the Object object, but how about this:
var myObject = { 'a': 1, 'b': 2, 'c': 3 };
Object.keys(myObject).map(function(key, index) {
myObject[key] *= 2;
});
console.log(myObject);
// => { 'a': 2, 'b': 4, 'c': 6 }
But you could easily iterate over an object using for ... in:
var myObject = { 'a': 1, 'b': 2, 'c': 3 };
for (var key in myObject) {
if (myObject.hasOwnProperty(key)) {
myObject[key] *= 2;
}
}
console.log(myObject);
// { 'a': 2, 'b': 4, 'c': 6 }
Update
A lot of people are mentioning that the previous methods do not return a new object, but rather operate on the object itself. For that matter I wanted to add another solution that returns a new object and leaves the original object as it is:
var myObject = { 'a': 1, 'b': 2, 'c': 3 };
// returns a new object with the values at each key mapped using mapFn(value)
function objectMap(object, mapFn) {
return Object.keys(object).reduce(function(result, key) {
result[key] = mapFn(object[key])
return result
}, {})
}
var newObject = objectMap(myObject, function(value) {
return value * 2
})
console.log(newObject);
// => { 'a': 2, 'b': 4, 'c': 6 }
console.log(myObject);
// => { 'a': 1, 'b': 2, 'c': 3 }
Array.prototype.reduce reduces an array to a single value by somewhat merging the previous value with the current. The chain is initialized by an empty object {}. On every iteration a new key of myObject is added with twice the key as the value.
Update
With new ES6 features, there is a more elegant way to express objectMap.
const objectMap = (obj, fn) =>
Object.fromEntries(
Object.entries(obj).map(
([k, v], i) => [k, fn(v, k, i)]
)
)
const myObject = { a: 1, b: 2, c: 3 }
console.log(objectMap(myObject, v => 2 * v))
How about a one-liner in JS ES10 / ES2019 ?
Making use of Object.entries() and Object.fromEntries():
let newObj = Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, v * v]));
The same thing written as a function:
function objMap(obj, func) {
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, func(v)]));
}
// To square each value you can call it like this:
let mappedObj = objMap(obj, (x) => x * x);
This function uses recursion to square nested objects as well:
function objMap(obj, func) {
return Object.fromEntries(
Object.entries(obj).map(([k, v]) =>
[k, v === Object(v) ? objMap(v, func) : func(v)]
)
);
}
// To square each value you can call it like this:
let mappedObj = objMap(obj, (x) => x * x);
With ES7 / ES2016 you can't use Objects.fromEntries, but you can achieve the same using Object.assign in combination with spread operators and computed key names syntax:
let newObj = Object.assign({}, ...Object.entries(obj).map(([k, v]) => ({[k]: v * v})));
ES6 / ES2015 Doesn't allow Object.entries, but you could use Object.keys instead:
let newObj = Object.assign({}, ...Object.keys(obj).map(k => ({[k]: obj[k] * obj[k]})));
ES6 also introduced for...of loops, which allow a more imperative style:
let newObj = {}
for (let [k, v] of Object.entries(obj)) {
newObj[k] = v * v;
}
array.reduce()
Instead of Object.fromEntries and Object.assign you can also use reduce for this:
let newObj = Object.entries(obj).reduce((p, [k, v]) => ({ ...p, [k]: v * v }), {});
Inherited properties and the prototype chain:
In some rare situation you may need to map a class-like object which holds properties of an inherited object on its prototype-chain. In such cases Object.keys() and Object.entries() won't work, because these functions do not include the prototype chain.
If you need to map inherited properties, you can use for (key in myObj) {...}.
Here is an example of such situation:
const obj1 = { 'a': 1, 'b': 2, 'c': 3}
const obj2 = Object.create(obj1); // One of multiple ways to inherit an object in JS.
// Here you see how the properties of obj1 sit on the 'prototype' of obj2
console.log(obj2) // Prints: obj2.__proto__ = { 'a': 1, 'b': 2, 'c': 3}
console.log(Object.keys(obj2)); // Prints: an empty Array.
console.log(Object.entries(obj2)); // Prints: an empty Array.
for (let key in obj2) {
console.log(key); // Prints: 'a', 'b', 'c'
}
However, please do me a favor and avoid inheritance. :-)
No native methods, but lodash#mapValues will do the job brilliantly
_.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
// → { 'a': 3, 'b': 6, 'c': 9 }
It's pretty easy to write one:
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;
}
with example code:
> 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 }
NB: this version also allows you to (optionally) set the this context for the callback, just like the Array method.
EDIT - changed to remove use of Object.prototype, to ensure that it doesn't clash with any existing property named map on the object.
You could use Object.keys and then forEach over the returned array of keys:
var myObject = { 'a': 1, 'b': 2, 'c': 3 },
newObject = {};
Object.keys(myObject).forEach(function (key) {
var value = myObject[key];
newObject[key] = value * value;
});
Or in a more modular fashion:
function map(obj, callback) {
var result = {};
Object.keys(obj).forEach(function (key) {
result[key] = callback.call(obj, obj[key], key, obj);
});
return result;
}
newObject = map(myObject, function(x) { return x * x; });
Note that Object.keys returns an array containing only the object's own enumerable properties, thus it behaves like a for..in loop with a hasOwnProperty check.
This is really annoying, and everyone in the JS community knows it. There should be this functionality:
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}
here is the naïve implementation:
Object.map = function(obj, fn, ctx){
const ret = {};
for(let k of Object.keys(obj)){
ret[k] = fn.call(ctx || null, k, obj[k]);
});
return ret;
};
it is super annoying to have to implement this yourself all the time ;)
If you want something a little more sophisticated, that doesn't interfere with the Object class, try this:
let 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;
});
but it is safe to add this map function to Object, just don't add to Object.prototype.
Object.map = ... // fairly safe
Object.prototype.map ... // not ok
I came here looking to find and answer for mapping an object to an array and got this page as a result. In case you came here looking for the same answer I was, here is how you can map and object to an array.
You can use map to return a new array from the object like so:
var newObject = Object.keys(myObject).map(function(key) {
return myObject[key];
});
JavaScript just got the new Object.fromEntries method.
Example
function mapObject (obj, fn) {
return Object.fromEntries(
Object
.entries(obj)
.map(fn)
)
}
const myObject = { a: 1, b: 2, c: 3 }
const myNewObject = mapObject(myObject, ([key, value]) => ([key, value * value]))
console.log(myNewObject)