Array.flat/flatMap and Object.fromEntries

On the podcast Real Talk JavaScript Episode 46: Using New JavaScript Features, the brilliant Tara Manicsic talked about the TC39 intake process and some of the new ES2019 features she is excited about: mainly Array.flat/flatMap and Object.fromEntries. So let’s see what this is about.

Array.flat and Array.flatMap

The documentation says:

Array.prototype.flat returns a new array with all sub-array elements concatenated into it recursively up to the specified depth.

Array.prototype.flatMap first maps each element using a mapping function, then flattens the result into a new array. It is identical to a map followed by a flatten of depth 1, but flatMap is quite often useful and merging both into one method is slightly more efficient.

Let’s break this down with actual code samples.

Array.prototype.flat

This means that an array containing other arrays can be “flattened” into another array: [[1, 2, 3], [4, 5, 6]] -> [1, 2, 3, 4, 5, 6]

And this can be done at multiple depths:

[[1, 2, 3], [4, 5, 6], [7, [8, 9]]] can be flattened to [1, 2, 3, 4, 5, 6, 7, 8, 9] and so on.

Normally this can be achieved using a recursive function, or one of many other solutions, but that’s not much fun to write, and recursion is easy to get wrong. The flat function is super convenient and avoids spending time rewriting something that’s been done to death or relying on a convenience library like lodash. The flat function takes in a depth argument (1 by default) that allows the caller to specify how many levels should be flattened.

const numbers = [[1, 2, 3], [4, 5, 6], [7, [8, 9]]];
numbers.flat(); // [1, 2, 3, 4, 5, 6, 7, [8, 9]];
numbers.flat(1); // [1, 2, 3, 4, 5, 6, 7, [8, 9]]; (same as above)
numbers.flat(2); // [1, 2, 3, 4, 5, 6, 7, 8, 9];

Array.prototype.flatMap

The flatMap function is a like doing a map, followed by a flat, and not the other way around as the name would imply.

Without flat or flatMap, we would have to write this:

const words = ["it's always", "sunny in", "philadelphia"];
words.reduce((a, w) => a.concat(w.split(" ")), []); // ["it's", "always", "sunny", "in", "philadelphia"]

With flat, this is now possible:

const words = ["it's always", "sunny in", "philadelphia"];
words.map(x => x.split(' ')).flat(1); // ["it's", "always", "sunny", "in", "philadelphia"]

With flatMap, it’s even easier:

const words = ["it's always", "sunny in", "philadelphia"];
words.flatMap(x => x.split(' ')); // ["it's", "always", "sunny", "in", "philadelphia"]

Object.fromEntries

To understand Object.fromEntries, let’s first look at Object.entries. This is a convenient way to convert and array to an object, something that is done all the time.

Let’s say a service returns something like this:

{
"1": {
"id": 1,
"name": "Joe"
},
"2": {
"id": 2,
"name": "Mary"
}
}

This kind of payload is pretty typical, and it’s not far fetched to need to iterate over it, and one way to do that is to convert it to an array.

For this I can use Object.entries

Object.entries(payload);

Each key/value pair is stored as an array in an array, so our payload would become:

[
["1", { id: 1, name: "Joe" }],
["2", { id: 2, name: "Mary" }]
];

Pretty useful!

Object.fromEntries is the exact opposite, it converts an array to an object:

const array = [
[1, { id: 1, name: "John" }],
[2, { id: 2, name: "Mary" }]
];
const users = Object.fromEntries(array);
// {"1": { id: 1, name: "John" }, "2": { id: 2, name: "Mary" }}

Without Object.fromEntries, we’d need to write something like this:

array.reduce((acc, v) => {
acc[v[0]] = v[1];
return acc;
}, {});

It’s easy to see how Object.fromEntries simplifies code!

Learn more about upcoming features in JavaScript (like a stable Array.prototype.sort()) on Axel Rauschmayer’s site: https://2ality.com

Previously Paris and Geneva, currently New York. Can also be found at https://dev.to/arnaud

Love podcasts or audiobooks? Learn on the go with our new app.