map function for objects (instead of arrays)

There is no native map to the Object object, but how about this:

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

Object.keys(myObject).forEach(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)) 

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.


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 }