Telerik blogs

ECMAScript 2023 (ES14) introduced several enhancements to JavaScript, optimizing both functionality and expressiveness. This article shows you the latest additions: the much-anticipated findLast and findLastIndex array methods, new immutable array methods like toSorted and toSpliced, symbols as WeakMap keys, and the inclusion of Hashbang Grammar.

Since the introduction of ES2015, commonly known as ES6, JavaScript has been evolving at a dynamic pace. With new functionality being added every year, the latest release—ECMAScript 2023 (ES14)—brings a number of useful features to JavaScript.

In this article, we will delve into the latest additions—new array methods, symbols as WeakMap keys and Hashbang Grammar support.

New Array Methods: findLast and findLastIndex

findLast Array Method

ES2023 introduced the findLast array method, a very useful addition that simplifies the process of locating the last element in an array that satisfies a given predicate function. Let’s illustrate this with an example:

const numbers = [1, 2, 3, 4, 5, 6, 7]
const lastEvenNum = numbers.findLast(number => number % 2 === 0)
// lastEvenNum is 6

With findLast, you can quickly pinpoint the last matching element in an array. Before this, there were a few different solutions to achieving this result. For example, we could first reverse an array and then find the first element that matches the predicate.

const numbers = [1, 2, 3, 4, 5, 6, 7]
const lastEvenNum = [...numbers].reverse().find(number => number % 2 === 0)
// lastEvenNum is 6

This solution is OK when not dealing with very large arrays. The code above creates a new copy of the numbers array, reverses it and then finds the first element that matches the predicate. The cost of additional operations is negligible if you are dealing with small datasets.

A more performant approach requires looping through the numbers array just once and assigning values that match the predicate to a variable.

const numbers = [1, 2, 3, 4, 5, 6, 7]
let lastEvenNum

for (const num of numbers) {
  if (num % 2 === 0) {
    lastEvenNum = num
  }
}
// lastEvenNum is 6

This solution is more imperative, but is much faster, as it requires only one loop and doesn’t involve copying the numbers array and reversing it.

findLastIndex Array Method

Building on the concept of finding the last element, ES2023 also introduced findLastIndex. This method returns the index of the last element that meets a specific condition. Here’s a practical application:

const numbers = [1, 2, 3, 4, 5, 6, 7]
const lastEvenNumIndex = numbers.findLastIndex(number => number % 2 === 0)
// lastEvenNumIndex is 5

Below, you can see how we can find an index of the last element that matches the predicate using a for loop.

let lastEvenNumIndex;

for (let i = 0; i <= numbers.length; i++) {
  const num = numbers[i];
  if (num % 2 === 0) {
    lastEvenNumIndex = i;
  }
}
// lastEvenNumIndex is 5

The findLastIndex method is much cleaner and more declarative than the imperative for loop solution.

New Immutable Array Methods: toSorted, toSpliced and with

findLast and findLastIndex are not the only array methods introduced in ES2023. Other new array methods are toSorted, toSpliced and with.

But wait, don’t we already have sort and splice methods? Why do we need toSorted and toSpliced?

The problem with sort and splice methods is that they mutate the original array they are called on. Here’s an example:

const fruits = ['banana', 'kiwi', 'apple', 'orange']
const sortedFruits = fruits.sort((a, b) => a.localeCompare(b))
// sortedFruits is ['apple', 'banana', 'kiwi', 'orange']
// fruits also is now ['apple', 'banana', 'kiwi', 'orange']

The sortedFruits const receives a sorted array of fruits. However, the fruits array was also modified. This behavior can lead to accidental data mutations that were not expected.

The same applies to the splice method. The splice method can be used to add, replace and remove items from an array, but it also mutates the original array. That’s where the new methods come in. Let’s have a look at each of the newly added methods.

toSorted Array Method

The toSorted method, as you probably already guessed, is a new alternative to the sort method. It allows you to create a sorted version of an array without altering the original. Here’s an example of sorting fruits alphabetically, but this time with the toSorted method.

const fruits = ['banana', 'kiwi', 'apple', 'orange']
const sortedFruits = fruits.toSorted((a, b) => a.localeCompare(b))
// sortedFruits is ['apple', 'banana', 'kiwi', 'orange']
// fruits is ['banana', 'kiwi', 'apple', 'orange']

The toSorted method creates a copy instead of mutating the original array. This results in more predictable code and prevents accidental data mutations.

toSpliced Array Method

With toSpliced, you can create a new array by splicing elements without modifying the source array.

const items = ['carrot', 'banana', 'potato']
const vegetables = items.toSpliced(1, 1)
// vegetables is ['carrot', 'potato']

This method is particularly handy when you need to manipulate arrays without side effects.

with Array Method

Completing the set of new array methods is the with method. It enables you to replace an element at a specified index, creating a new array while preserving the original:

const vegetables = ['carrot', 'potato']
const updatedVegetables = vegetables.with(1, 'parsnip')
// updatedVegetables is ['carrot', 'parsnip']

The with method is an immutable equivalent of updating an array using the bracket notation.

const vegetables = ['carrot', 'potato']
const newVegetables = [...vegetables]
newVegetables[1] = 'parsnip'
// updatedVegetables is ['carrot', 'parsnip']

Symbols as WeakMap Keys

Another interesting change in ES2023 is the inclusion of symbols as WeakMap keys. Previously, symbols were not allowed in this context. This enhancement offers new possibilities, as illustrated in the following example:

const weakMap = new WeakMap()
const uniqueSymbolKey = Symbol('myUniqueSymbolKey')
weakMap.set(uniqueSymbolKey, 'value')
console.log(weakMap.get(uniqueSymbolKey)) // 'value'

This update extends the versatility of symbols and WeakMaps, which are a great tool for associating additional information to certain values without affecting garbage collection.

Hashbang Grammar

JavaScript in ES2023 now embraces Hashbang Grammar, allowing developers to specify the program or engine used to execute a script. This feature is useful in various environments and can be implemented as follows:

#!/usr/bin/env node

console.log('I am a JS script that should be run in Node.js!')

Conclusion

ES2023 ushered in a new era of JavaScript development, marked by improved functionality and expressiveness. The new array methods, immutable array methods, symbols as WeakMap keys, and Hashbang Grammar collectively contribute to a more versatile and efficient language.


Thomas Findlay-2
About the Author

Thomas Findlay

Thomas Findlay is a 5-star rated mentor, full-stack developer, consultant, technical writer and the author of “React - The Road To Enterprise” and “Vue - The Road To Enterprise.” He works with many different technologies such as JavaScript, Vue, React, React Native, Node.js, Python, PHP and more. Thomas has worked with developers and teams from beginner to advanced and helped them build and scale their applications and products. Check out his Codementor page, and you can also find him on Twitter.

Related Posts

Comments

Comments are disabled in preview mode.