map for objects (instead of arrays)

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.)

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

Object.keys(myObject).map(function(value, index) {
   myObject[value] *= 2;
});

console.log(myObject);

// => { 'a': 2, 'b': 4, 'c': 6 }

But you could easily iterate over an object using for ... in:

for(var key in myObject) {
    if(myObject.hasOwnProperty(key)) {
        myObject[key] *= 2;
    }
}

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 newObject = Object.keys(myObject).reduce(function(previous, current) {
    previous[current] = myObject[current] * myObject[current];
    return previous;
}, {});

console.log(newObject);
// => { 'a': 1, 'b': 4, 'c': 9 }

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 its square as value.

It's pretty easy to write one and add it to Object.prototype so that it's available on all objects:

Object.defineProperty(Object.prototype, 'map', {
    value: function(f, ctx) {
        ctx = ctx || this;
        var self = this, result = {};
        Object.keys(self).forEach(function(k) {
            result[k] = f.call(ctx, self[k], k, self); 
        });
        return result;
    }
});

Using Object.defineProperty ensures that the newly added function doesn't appear in the list of enumerable properties of every Object.

> o = { a: 1, b: 2, c: 3 };
> r = o.map(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.

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 }

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.

The map function does not exist on the Object.prototype however you can emulate it like so

var myMap = function ( obj, callback ) {

    var result = {};

    for ( var key in obj ) {
        if ( Object.prototype.hasOwnProperty.call( obj, key ) ) {
            if ( typeof callback === 'function' ) {
                result[ key ] = callback.call( obj, obj[ key ], key, obj );
            }
        }
    }

    return result;

};

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

var newObject = myMap( myObject, function ( value, key ) {
    return value * value;
});

If you're interested in mapping not only values but also keys, I have written Object.map(valueMapper, keyMapper), that behaves this way:

var source = { a: 1, b: 2 };
function sum(x) { return x + x }

source.map(sum);            // returns { a: 2, b: 4 }
source.map(undefined, sum); // returns { aa: 1, bb: 2 }
source.map(sum, sum);       // returns { aa: 2, bb: 4 }