Neues Jahr, neue Features: Für das 2022er Update der ECMAScript-Spezifikation stehen zahlreiche neue Proposals bereit. Einige davon haben bereits Stufe 4 des TC39-Approval-Prozesses erreicht und werden damit sicher in die neue Version aufgenommen.
Top-Level await
await konnten JS-Entwickler:innen bisher nur innerhalb einer async-Funktion verwenden:
(async () => {
await fetch(/* ...*/)
})()
Das wird sich mit ECMAScript 2022 ändern. In TypeScript wurde das Feature bereits 2020 in Version 3.8 eingeführt. Top-Level await stellt sicher, dass Module erst auf asynchrone Importe zugreifen können, wenn sie vollständig initialisiert sind. Ein weiterer Vorteil ist, dass das Feature Asynchronität transparent verwaltet: Wird ein Modul von von einer anderen Datei importiert, muss diese nicht wissen, ob das importierte Modul asynchron ist oder nicht.
Top-Level await
ermöglicht es beispielsweise, Module dynamisch zu laden:
const params = new URLSearchParams(location.search);
const language = params.get('lang');
const messages = await import(`./messages-${language}.mjs`); // (A)
console.log(messages.welcome);
Auch kann es eingesetzt werden, um ein Fallback zu hinterlegen, falls das eigentlich zu ladende Modul nicht geladen werden kann:
let lodash;
try {
lodash = await import('https://primary.example.com/lodash');
} catch {
lodash = await import('https://secondary.example.com/lodash');
}
Oder auch, um die Ressourcen zuerst zu verwenden, die als erste geladen werden:
const resource = await Promise.any([
fetch('http://example.com/first.txt')
.then(response => response.text()),
fetch('http://example.com/second.txt')
.then(response => response.text()),
]);
Aufgrund der Verwendung von promise.any()
wird in diesem Beispiel die Variable resource
von dem Download initialisiert, der zuerst beendet ist.
Von Nachteil ist allerdings offenbar, dass Top-Level await
die Initialisierung der importierenden Module verzögert. Daher wird empfohlen, das Feature nur sparsam zu verwenden.
Neue Array-Methode at()
ECMAScript führt eine neue Array-Methode namens at()
ein. Sie soll es ermöglichen, Array-Objekte von deren Ende her zu indizieren. Es handelt sich dabei zwar um ein vergleichsweise kleines Feature, trotzdem dürfte es Entwickler:innen die Arbeit mit Arrays erleichtern. Eine at()
-Methode mit einer positiven Zahl wirkt sich dabei so aus, als würdet ihr via Bracket Operator []
auf die Objekte zugreifen. Im Unterschied zur neuen at()
-Methode unterstützt dieser jedoch keine negativen Indices.
Anstelle von
const arr = [1,2,3,4]
arr[arr.length - 2] // 3
arr.slice(-2)[0] // 3
const str = "1234"
str[str.length - 2] // '3'
str.slice(-2)[0] // '3'
ermöglicht at() folgende Schreibweise:
const arr = [1,2,3,4]
arr.at(-2) // 3
const str = "1234"
str.at(-2) // '3'
Mächtigere Klassen: Private Slots und Methods
Klassen gibt es seit ECMAScript 6 in JavaScript. Allerdings sind sie weniger ausgereift als in objektorientierten Programmiersprachen. Ein Workaround für viele JS-Entwickler:innen ist es, dort TypeScript zu verwenden, wo Klassen im Allgemeinen mehr Möglichkeiten bieten. Mit ECMAScript 2022 bieten Klassen in JavaScript künftig die Möglichkeit, mit sogenannten Private Slots private Eigenschaften einer Klasse festzulegen. Wird versucht, außerhalb der Klasse auf sie zuzugreifen, erhalten Entwickler:innen künftig eine Fehlermeldung. Statt der Einführung eines private-Keywords äquivalent zum public-Keyword hat sich das ECMAScript-Team interessanterweise entschieden, #
zu nutzen.
class Dog {
#name = "Monty";
setName(name) {
this.#name = name;
}
}
const dog = new Dog()
dog.#name = 'Marty' // ERROR!
dog.setName('Amy') // Is fine
Das Gleiche gilt für private Methoden:
class Dog {
name = "Monty";
constructor(name) {
this.#setName('Marty') // OK
}
#setName(name) {
this.name = name;
}
}
const dog = new Dog()
dog.#setName('Marty') // ERROR!
Hilfe beim Debugging: Error cause
Fehler werden oft gewrappt, um aussagekräftigere Fehlermeldungen zu liefern und den Fehlerkontext zu dokumentieren. Dabei kann es aber vorkommen, dass der ursprüngliche Error nicht mehr enthalten ist. Das neue error-cause-Feature in ECMAScript 2022 bietet eine standardisierte Möglichkeit, den ursprünglichen Fehler an den gewrappten Fehler anzuhängen. Dem error
-Konstruktor wird dabei einfach die Option cause
hinzugefügt. Zudem ermöglicht ein cause
-Feld das Abrufen des ursprünglichen Errors.
try {
somethingThatWillThrowAnError()
} catch (error) {
throw new Error('I am the result of another error', { cause: error })
}
Offenbar eignet sich das Feature besonders gut für das Verketten von Fehlern – eine Möglichkeit, die einigen Entwickler:innen vielleicht aus anderen Programmiersprachen wie zum Beispiel Java bekannt vorkommen dürfte. Allerdings wird das Feature bisher nicht von allen Browsern unterstützt. Node.js unterstützt das Feature seit Version 16.9.
Darüber hinaus werden in ECMAScript 2022 natürlich noch weitere Features eingeführt. Im Detail nachlesen, was die neue Spezifikation sonst noch zu bieten hat, könnt ihr beispielsweise in Axel Rauschmeiers Buch beziehungsweise Website „JS for impatient programmers“.