ES2023: What’s new ? Plus a sneak peek into ES2024

Kyle Carson
Version 1
Published in
5 min readJul 28, 2023

ECMAScript is a JavaScript standard developed by Ecma International. Every June since 2015, a new major version has been released, and this year was no different with 6 new exciting methods introduced. We will take a deep dive into each of these new features as well as what is already proposed for 2024. To help jog your memory, first, let’s reflect on what has been added over recent years:

A Rundown on ES2023

Array Find From Last

When searching for a value within an array, typically we use the .find()method. This method returns the first element in the array that satisfies the provided testing function. If we want the index of the value instead we can use .findIndex(). The issue with these methods is that they iterate over the array from left to right. If you know however that the value you are looking for is likely to be at the end of the array, it will take a lot of iterations to get there.

The workaround to this would be to reverse the array but this means either: 1) unnecessary mutation (by reversing array) or 2) unnecessary copying of the array (to avoid mutation). In addition to this, for .findIndex(), you would need to undergo complex index re-calculation as reversing the array would change all the original indexes.

This is where ES2023 comes in, with two new methods: .findLast() and .findLastIndex(). Both of these methods do what their names suggest — they search the array from right to left avoiding the unnecessary workarounds described above.

//we want to find the value 82 towards the end of the list
const numbers = [42,13,7,21,82,100];

//Before the proposal

//find
[...numbers].reverse().find(n => n.value === 82); //82 iterates left to right

//findIndex
numbers.length - 1 - [...numbers].reverse().findIndex(n => n.value === 82); //4
numbers.length - 1 - [...numbers].reverse().findIndex(n => n.value === 98); //should be -1, but 6

//After the proposal

//find
numbers.findLast(n => n.value === 82); //82 iterates right to left

//findIndex
numbers.findLastIndex(n => n.value === 82); //82
numbers.findLastIndex(n => n.value === 98); //-1

Hashbang Grammar

Hashbangs #! are a sequence of characters at the beginning of a unix-based script which determine what interpreter the script will be executed with. This allows the execution of JavaScript scripts as standalone executables. Until now it was expected that the JavaScript runtime environment would handle the Hashbang syntax and if all else failed, it would simply be ignored. However, there has been no formal standard to handle this syntax and this is what Bradley Farias’s proposal introduces in ES2023.

#!/usr/bin/env node
console.log('Hello, World!');

Symbols as WeakMap Keys

Previously WeakMaps only supported Objects as keys despite Symbols also having the feature of being unique and non-replicable. ES2023 rectifies this, enabling the use of Symbols as keys enabling more flexibility in utilising the memory-optimisation benefits of WeakMaps.

const weakMap = new WeakMap();
const key = Symbol("key1");
WeakMap.set(key, "Welcome Symbols to WeakMap !");
console.log(weakMap.get(key)); // Welcome Symbols to WeakMap !

Change Array by Copy

The JavaScript array methods .reverse(),.sort() and .splice() all mutate the original array. This proposal introduces three equivalent methods (.toReversed(), .toSorted() and.toSpliced()) which instead returns a copy leaving the original array untouched. As well as this the .with(index,value)method was introduced, which returns a copy of the array with the value at the specified index replaced. These additions help expand the versatility of array manipulations, check out the examples below:

// toReversed() returns a copy of the reversed array leaving original untouched
const sequence = [1,2,3,4];
const reversed = original.toReversed();
console.log(reversed); // [4,3,2,1]
console.log(sequence); // [1,2,3,4]

//toSorted() returns a copy of the sorted array leaving original untouched
const unsorted = [1,3,4,2];
const sorted = unsorted.toSorted();
console.log(sorted); // [1,2,3,4]
console.log(unsorted); // [1,3,4,2]

//toSpliced() returns spliced copy of array leaving original untouched
const original = [1,4];
const spliced = original.toSpliced();
console.log(spliced); //[1,2,3,4]
console.log(original); // [1,4]

//with() returns a copy of the altered array leaving original untouched
const unaltered = [1,2,4];
const altered = unaltered.with(2,3);
console.log(altered); // [1,2,3]
console.log(unaltered); // [1,2,4]

What awaits us in ES2024 ?

So far there are three proposals at finished status (stage 4) and are on track for inclusion in the ECMAScript 2024 snapshot:

Well-Formed Unicode Strings

A lone surrogate is described as a string which contains Unicode characters in the range 0xD800–0xDBFF to0xDC00–0xDFFF. A String is not well-formed if it contains a lone surrogate. This proposal introduces two new methods which help deal with non-well-formed strings:

String.prototype.isWellFormed

Returns true if the string does not contain a lone surrogate. This is particularly beneficial in the scenario for interfaces between JavaScript/web APIS.

const str1 = "ab\uD800";
const str2 = "abc";
console.log(str1.isWellFormed()); //false
console.log(str2.isWellFormed()); //true

String.prototype.toWellFormed

Returns the string with all lone surrogates of the string replaced with the unicode replacement character U+FFFD. This mimics the operation already performed within non-ECMAScript APIS already.

const str1 = "ab\uD800";
const str2 = "abc";
console.log(str1.toWellFormed()); //ab�
console.log(str2.toWellFormed()); // abc

Regular Expression v flag with set notation and properties of strings

Regular expressions are one of the most beneficial tools within JavaScript and have been supported since 1999. They have been continuously improved over the years since and it looks like ES2024 is set to gain more enhancements. It looks to introduce the unicodeSets mode which is enabled using the vflag. Notable features of this flag include Unicode properties of strings, set notation and improved case-insensitive matching for negated character classes. For in-depth examples of the new features please refer to the proposal documentation.

Atomics.waitAsync

This method has been in the pipeline for quite some time but it reached stage 4 status in the May 2023 TC39 meeting. It is a static method which waits asynchronously on a shared memory location and returns a Promise. Unlike Atomics.wait(), it is non-blocking and can be used on the main thread.

const arrayBuffer = new SharedArrayBuffer(1024);
const arr = new Int32Array(arrayBuffer);

//This will wait for position 0 on the int32 array and expect a result of 0,
//waiting for 500 ms
Atomics.waitAsync(arr, 0 , 0 , 500);
// { async: true, value: Promise {<pending>}}

//the notify method awakes the array and the promise is fulfilled
Atomics.notify(arr, 0);
// { async: true, value: Promise {<fulfilled>: 'ok'} }

And that’s a wrap…

Ecma International strives to continuously develop JavaScript and this year was no different. With three stage 4 proposals already, we are excited for what's to come. For more examples and in-depth descriptions of the new features described in this blog, please refer to the tc39 proposals repository.

About the Author:
Kyle Carson is a is Full Stack Java Developer here at Version 1.

--

--