ECMAScript 2023 - Exploring New Features

As JavaScript continues to evolve, developers like us eagerly anticipate the new features introduced in each ECMAScript update. In this blog, we will take a closer look at some exciting new functionalities of ECMAScript 2023. Let’s explore the latest additions to the JavaScript language.

1. Introducing findLast and findLastIndex

Need: Working with arrays often involves searching for specific elements. The find method was introduced to simplify this process, but it only returns the first matching element. However, certain scenarios require us to search from the end of the array to find the last matching element. This is where findLast and findLastIndex come into play.

There are scenarios where searching from the last element is more practical:

Time-Based Logs: Imagine an array of log entries sorted by timestamp. If we want to find the last log entry from a specific user, searching from the end ensures we get the most recent entry.

Reverse Priority Queue: In some cases, we might maintain a priority queue where the most recent items have higher priority. When retrieving items with the highest priority, searching from the last element ensures we get the latest high-priority item.

Let’s consider a scenario where we have an array of users, and we want to find the last user who is over the age of 18.

// Old Way
const users = [
{id: 1, name: 'user1', age: 19},
{id: 2, name: 'user2', age: 14},
{id: 3, name: 'user3', age: 22},
{id: 4, name: 'user4', age: 13},
];

let lastUser;
for (let i = users.length - 1; i >= 0; i--) {
if (users[i].age > 18) {
lastUser = users[i];
break;
}
}
console.log(lastUser); => {id: 3, name: 'user3', age: 22}

// using findLast()
const lastUser = users.findLast(user => user.age > 18);
console.log(lastUser); => {id: 3, name: 'user3', age: 22}

Similarly, the findLastIndex method can be valuable when we need to find the index of the last element that satisfies a condition.

Suppose we have an array of temperatures recorded throughout the day, and we want to find the last instance when the temperature exceeded 30 degrees Celsius.

// Old Way
const temperatures = [25, 28, 30, 32, 33, 31, 29];
let lastIndex = -1;
for (let i = temperatures.length - 1; i >= 0; i--) {
if (temperatures[i] > 30) {
lastIndex = i;
break;
}
}
console.log("Last index with temperature > 30:", lastIndex); => Last index with temperature > 30 (New): 5

// using findLastIndex()
const lastIndexNew = temperatures.findLastIndex(temp => temp > 30);
console.log("Last index with temperature > 30 (New):", lastIndexNew); => Last index with temperature > 30 (New): 5

2. Change Array by copy:

Need: Manipulating arrays is a fundamental aspect of JavaScript programming. ECMAScript 2023 introduces enhanced array methods which allows us to make changes to an array while keeping the original array unchanged. Instead of modifying the array directly, these methods create a new copy of the array with the desired changes. This helps maintain the integrity of the original array while still allowing us to work with modified versions when needed.

Let’s explore these new methods which are added to the Array.prototype and TypedArray.prototype .

i. toReversed():

Let’s consider a scenario where we have an array of months representing the months of a year in chronological order, but we want to display them in reverse order.

const months = ['January', 'February', 'March', 'April', 'May'];

//using reverse()
const reversedMonths = months.reverse();
console.log(months) => ['May', 'April', 'March', 'February', 'January']; // Original array is altered
console.log(reversedMonths) => ['May', 'April', 'March', 'February', 'January'];

//using toReversed()
const reversedMonths = months.toReversed();
console.log(months) => ['January', 'February', 'March', 'April', 'May']; // Original array remains unchanged
console.log(reversedMonths) => ['May', 'April', 'March', 'February', 'January'];

ii. toSorted():

Imagine we want to sort the set of prime numbers, without altering the original array.

const prime = [13,7,17,2];

//using sort()
const sortPrime = prime.sort();
console.log(prime) => [2,7,13,17]; // Original array is altered
console.log(sortPrime) => [2,7,13,17];

//using toSorted()
const sortPrime = prime.toSorted();
console.log(prime) => [13,7,17,2]; // Original array remains unchanged
console.log(sortPrime) => [2,7,13,17];

iii. toSpliced():

Imagine we have a list of items, and we want to remove a specific item without altering the original array.

const numbers = [1,2,3,4,5,6];

//using splice()
const spliceNumbers = numbers.splice(4,1);
console.log(numbers) => [1,2,3,4,6]; // Original array is altered
console.log(spliceNumbers) => [1,2,3,4,6];

//using toSpliced()
const sortPrime = prime.toSorted(4,1);
console.log(prime) => [1,2,3,4,5,6]; // Original array remains unchanged
console.log(sortPrime) => [1,2,3,4,6];

iv. with():

Need: Updating elements within an array is a common operation in JavaScript. However, directly modifying array elements can lead to unintended side effects. The with() method, introduced in ECMAScript 2023, offers a safe way to update elements in an array without altering the original array.

Imagine we have an array of usernames, and we want to update a specific username without altering the original array.

const usernames = ['user1', 'user2', 'user3'];

//old way of updating array value
usernames[1] = 'newUser';
console.log(usernames) => ['user1', 'newUser', 'user3']

// using with()
const updatedUsernames = usernames.with(1, 'newUser');
console.log(usernames) => ['user1', 'user2', 'user3'] //Original array remains unchanged
console.log(updatedUsernames) => ['user1', 'newUser', 'user3']

3. Hashbang Grammar:

Need: The introduction of Hashbang Grammar in ECMAScript 2023 allows us to use the shebang notation (#!) in the source code. This feature makes it easier to differentiate between scripts and modules and provides better compatibility with build tools and makes javascript consistent with other languages.

#!/usr/bin/env node

console.log('Hello from Hashbang Grammar!');

4. Symbols as WeakMap Keys:

Need: In JavaScript, using objects as keys for data storage can sometimes lead to unwanted side effects. Objects are reference types, and using them as keys can inadvertently cause memory leaks or unexpected behavior. Symbols, being unique and immutable, provide a solution to this issue, ensuring that the keys are distinct and safe from conflicts.

Imagine we are working on a library that manages private data for objects. We want to create a private storage mechanism using a Map but avoid potential conflicts with object keys. Symbols come to the rescue.

//old way
const privateData = new Map();
const obj = {};

privateData.set(obj, 'This is private data');
console.log(privateData.get(obj)); // Output: "This is private data"

//using WeakMap and symbol
const privateData = new WeakMap();
const obj = {label:'Private data'};

const key = Symbol('privateKey'); // Create a unique Symbol as the key
privateData.set(key, obj); // Use the Symbol key to associate private data
console.log(privateData.get(key)); // Output: {label:'Private data'}

We are using a WeakMap with Symbols as keys. Symbols are unique and immutable, making them perfect for use as keys. WeakMaps hold weak references to the keys, meaning that if the object used as a key is no longer referenced elsewhere, it can be garbage collected. This prevents memory leaks and unintended retention of objects in memory.

Conclusion:

The new ECMAScript 2023 update brings a host of exciting features to JavaScript, expanding the language’s capabilities and improving the overall developer experience. From enhanced array manipulation methods to more flexible key options. ECMAScript 2023 ensures that JavaScript developers can write code that is more efficient.

Need help on your Ruby on Rails or React project?

Join Our Newsletter