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 }