Introduction
Periodically, new features are introduced to Javascript - more accurately features are proposed with the ECMAScript standard then integrated into Javascript.
Over the years (just to name a few) we had ES6 which brought in the let
and const
keyword, ES2020 which had nullish coalescing, optional chaining etc.
The newest proposal, aptly named ES2023, has some new useful features concerning arrays we will get into shortly.
Array by copy
Some array methods mutate an array it was called upon, the most prominent of these being:
- sort
- splice
- reverse
For example:
const x = [3, 2, 1];
const y = x.sort();
console.log(y); // [1, 2, 3] <- Ok
console.log(x); // [1, 2, 3]
Calling the sort method mutated the original array, which might not be neccessary if you planned on keeping the original array the same.
You can get around this if you spread the original array (only if the members of the array are primitive types):
const x = [3, 2, 1];
const y = [...x].sort();
console.log(y); // [1, 2, 3]
console.log(x); // [3, 2, 1]
But why, if you could use a method for this? That's where the new to
methods come into play.
In this instance, the toSorted
method:
const x = [3, 2, 1];
const y = x.toSorted();
console.log(y); // [1, 2, 3]
console.log(x); // [3, 2, 1]
The proposal is described here, with the other methods being:
- toReversed
- toSorted
- toSpliced
- with
Array grouping
As the name implies, this method groups its members together with a provided condition akin to the GROUP BY
clause one can find in SQL.
Previously, a method that could be used to group elements together could be as follows:
/**
* Groups values in an array of objects.
* @param {any[]} array - The array of objects to be grouped by.
* @param {string} property - The property of the objects to group by.
* @return {any[]} Array of objects grouped by the provided property.
*/
export function groupBy(array, property) {
return array.reduce((memo, x) => {
if (!memo[x[property]]) {
memo[x[property]] = [];
}
memo[x[property]].push(x);
return memo;
}, {});
}
Let's say we have an array of employees, defined as such:
const employees = [
{ name: "Alina", company: "Google", id: 1 },
{ name: "Vika", company: "Coca Cola", id: 2 },
{ name: "Alex", company: "Jonson & Jonson", id: 3 },
{ name: "Vlad", company: "Google", id: 4 },
{ name: "Fibi", company: "Coca Cola", id: 5 },
{ name: "Joey", company: "Google", id: 6 }
];
If we wanted to group them together by the company, we'd use the method as follows:
const grouped = groupBy(employees, "company");
With the result being:
{
Google: [
{
name: "Alina",
id: 1
},
{
name: "Vlad",
id: 4
},
{
name: "Joey",
id: 6
}
],
"Coca Cola": [
{
name: "Vika",
id: 2
},
{
name: "Fibi",
id: 5
}
],
"Jonson & Jonson": [
{
name: "Alex",
id: 3
}
]
}
The same can now be achieved with the newly proposed methods, group
and groupToMap
.
The proposal is described here.
groupToMap
The groupToMap
method groups the elements of the calling array using the values returned by a provided testing function. The final returned Map
uses the unique values from the test function as keys, which can be used to get the array of elements in each group.
The method is primarily useful when grouping elements that are associated with an object, and in particular when that object might change over time. If the object is invariant, you might instead represent it using a string and group elements with group
.
For example, let's say we have an array of game items:
const items = [
{ name: "potion", type: "consumable", price: 25 },
{ name: "sword", type: "weapon", price: 425 },
{ name: "shield", type: "protection", price: 225 },
{ name: "helmet", type: "protection", price: 125 }
];
The code below uses groupToMap()
with an arrow function that returns the object keys named unaffordable
or affordable
, depending on whether the element has a price lesser than 150. The returned result
object is a Map
so we need to call get()
with the key to obtain the array.
const unaffordable = { unaffordable: true };
const affordable = { unaffordable: false };
const result = items.groupToMap(({ price }) =>
price < 150 ? affordable : unaffordable
);
console.log(result.get(affordable));
// expected output: [{ name: "potion", price: 25 }, { name: "helmet", price: 125 }]
group
The group
method groups the elements of the calling array according to the string values returned by a provided testing function. The returned object has separate properties for each group, containing arrays with the elements in the group.
This method should be used when group names can be represented by strings.
Using the method on the array mentioned beforehand, we get a result as follows:
const result = items.group(({ type }) => type);
{
consumable: [
{
name: "potion",
type: "consumable",
price: 25
}
],
weapon: [
{
name: "sword",
type: "weapon",
price: 425
}
],
protection: [
{
name: "shield",
type: "protection",
price: 225
},
{
name: "helmet",
type: "protection",
price: 125
}
]
}
Array from async
The array method called from
has been standardized and it is very useful for shallow copies of iterables or array like objects.
For example:
const letters = Array.from("hello"); // ["h", "e", "l", "l", "o"]
const squares = Array.from([4, 5, 6], (n) => n ** 2); // [16, 25, 36]
It also provides a mapping callback that can be used on every member of the array.
However, a similar method does not exist for async iterables. Let's say we have a function that generates numbers asynchronously:
async function* asyncGen(n) {
for (let i = 0; i < n; i++) yield i * 2;
}
Without a dedicated function, one would create an array as follows:
const arr = [];
for await (const v of asyncGen(4)) {
arr.push(v);
}
The result being [0, 2, 4, 6]
. Using the fromAsync
method, an equivalent process can be done:
const arr = await Array.fromAsync(asyncGen(4));
The proposal is described here.
Conclusion
Having looked at the newly proposed features, one can see that it is quite handy having them integrated into the default language features as you do not need to write your own implementations.
Top comments (0)