So .map itself only offers one value you care about...
That said, there are a few ways of tackling this:
// instantiation
const myMap = new Map([
[ "A", 1 ],
[ "B", 2 ]
]);
// what's built into Map for you
myMap.forEach( (val, key) => console.log(key, val) ); // "A 1", "B 2"
// what Array can do for you
Array.from( myMap ).map(([key, value]) => ({ key, value })); // [{key:"A", value: 1}, ... ]
// less awesome iteration
let entries = myMap.entries( );
for (let entry of entries) {
console.log(entry);
}
Note, I'm using a lot of new stuff in that second example...
...Array.from takes any iterable (any time you'd use [].slice.call( ), plus Sets and Maps) and turns it into an array... ...Maps, when coerced into an array, turn into an array of arrays, where el[0] === key && el[1] === value; (basically, in the same format that I prefilled my example Map with, above).
I'm using destructuring of the array in the argument position of the lambda, to assign those array spots to values, before returning an object for each el.
If you're using Babel, in production, you're going to need to use Babel's browser polyfill (which includes "core-js" and Facebook's "regenerator").
I'm quite certain it contains Array.from.
Videos
So .map itself only offers one value you care about...
That said, there are a few ways of tackling this:
// instantiation
const myMap = new Map([
[ "A", 1 ],
[ "B", 2 ]
]);
// what's built into Map for you
myMap.forEach( (val, key) => console.log(key, val) ); // "A 1", "B 2"
// what Array can do for you
Array.from( myMap ).map(([key, value]) => ({ key, value })); // [{key:"A", value: 1}, ... ]
// less awesome iteration
let entries = myMap.entries( );
for (let entry of entries) {
console.log(entry);
}
Note, I'm using a lot of new stuff in that second example...
...Array.from takes any iterable (any time you'd use [].slice.call( ), plus Sets and Maps) and turns it into an array... ...Maps, when coerced into an array, turn into an array of arrays, where el[0] === key && el[1] === value; (basically, in the same format that I prefilled my example Map with, above).
I'm using destructuring of the array in the argument position of the lambda, to assign those array spots to values, before returning an object for each el.
If you're using Babel, in production, you're going to need to use Babel's browser polyfill (which includes "core-js" and Facebook's "regenerator").
I'm quite certain it contains Array.from.
Just use Array.from(iterable, [mapFn]).
var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);
var newEntries = Array.from(myMap, ([key, value]) => [key, value + 1]);
var newMap = new Map(newEntries);
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))
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. :-)