App-Entwicklung mit JavaScript, Teil 2: Evolution einer Sprache

Mit ECMAScript 2015 folgte die wohl größte Umwälzung von JavaScript aller Zeiten. Lange vermisste Sprachkonstrukte kamen damit endlich auch ins Web. Seitdem kommt jedes Jahr ein neues JavaScript.

In Pocket speichern vorlesen Druckansicht 3 Kommentare lesen
Lesezeit: 7 Min.
Von
  • Christian Liebel
Inhaltsverzeichnis

Im ersten Teil dieser Mini-Serie zu JavaScript ging es um die Anfänge der Sprache, Stolperfallen, die einfache Handhabung zur Entwicklungszeit und die Entwicklung der Sprache bis zu ECMAScript 5 im Jahr 2009. Dort blieb JavaScript aber nicht stehen: 2015 folgte die vermutlich größte Umwälzung der Skriptsprache bisher. Seitdem sollen neue Ausgaben in einem jährlichen Zyklus erscheinen.

Mehr Infos

App-Entwicklung mit JavaScript

JavaScript wird bei der Ecma International standardisiert und dort in eine Spezifikation gegossen: 1999 erschien ECMAScript 3 und erst nach zehnjährigem Irren und einer ausgefallenen Version 4 kam JavaScript durch die Veröffentlichung von ECMAScript 5 wieder zurück in normales Fahrwasser. Prominenteste Änderung war die Einführung des Strict Mode, der einige Fehlerquellen beseitigt. Doch mit dieser Version sollte JavaScript noch nicht fertig sein. Sechs Jahre später, im Jahr 2015, folgte ECMAScript 2015, das manchmal auch als ECMAScript 6 (ES 6) bezeichnet wird.

Diese Ausgabe brachte viele Sprachfeatures ins Web, die von anderen Programmiersprachen wie C++, Java oder C# bekannt sind und im Web bislang schmerzlich vermisst wurden. Das schließt Klassen, Array-Funktionen höherer Ordnung, Lambda-Ausdrücke, Template-Strings sowie neue Methoden zur Variablendeklaration ein.

Eines der meistgeforderten Features war die Einführung von Klassen. Diese konnten zuvor allerdings auch schon über Konstruktorfunktionen abgebildet werden, im Übrigen inklusive Vererbung. Aber sie hießen eben nicht Klassen. Insofern handelt es sich bei der neuen Klasse lediglich um syntaktischen Zucker über längst bestehende Konstrukte.

// vor ES 2015
function Auto(farbe) {}
var auto = new Auto('gelb');

// ab ES 2015
class Auto {
constructor (farbe) { }
}
let auto = new Auto('rot');

.NET-Entwickler sind seit langem verwöhnt mit LINQ-Ausdrücken. ECMAScript 2015 liefert Array-Funktionen höherer Ordnung nach. Darunter gebräuchliche Funktionen wie map, filter oder forEach. Natürlich dürfen in diesem Zusammenhang auch Lambda-Ausdrücke nicht fehlen. Die sogenannten Arrow Functions gleichen ihren C#-Pendants.

// C#
(new[] {1, 2, 3}).Select(x => x * 3).Where(x => x < 7).ToList() // 3, 6

// ab ES 2015
[1, 2, 3].map(x => x * 3).filter(x => x < 7) // 3, 6

Ebenfalls neu sind die Template-Literale, wie sie zeitgleich in C# 6 unter dem Namen Interpolated Strings eingeführt wurden. Sie vereinfachen das Verketten von Zeichenfolgen:

// C#
var person = new { Name = "Astrid" };
var greeting = $"Hallo, {person.Name}!";

// ab ES 2015
const person = { name: 'Astrid' };
const greeting = `Hallo, ${person.name}!`;

Die Backtick-Syntax erlaubt in JavaScript zudem die Angabe mehrzeiliger String-Literale. Möglicherweise sind den Lesern in den obigen Listings die Schlüsselworte let und const aufgefallen. JavaScript kennt zur Deklaration "lokaler" Variablen das Schlüsselwort var, das jedoch eine Unhandlichkeit mit sich bringt. Raten Sie mit:

function varTest() {
var x = 31;
if (true) {
var x = 71;
console.log(x); // 71
}
console.log(x); // ???
}

Die Antwort auf dieses dem Mozilla Developer Network entnommenen Beispiel ist: 71! In Java würde ein solches Konstrukt nicht einmal kompilieren. In JavaScript verwirrt die Ausgabe, da die meisten vermutlich 31 erwartet hätten. Um dieses Block-Scoping (vereinfacht gesprochen "innerhalb geschwungener Klammern") zu erreichen, wurde das let-Schlüsselwort eingeführt. Wer im obigen Listing mindestens das innere var gegen let tauscht, erhält das erwartungskonforme Ergebnis 31. Zudem existiert noch const mit derselben Eigenschaft. So deklarierte Variablen dürfen jedoch nur einmal zugewiesen werden (read-only). Bei der Zuweisung von Objekten gilt das allerdings nur für die Referenz und nicht für Felder des Objekts.

In ECMAScript 2015 gibt es noch vieles andere mehr zu entdecken, zum Beispiel Operatoren zum Destrukturieren von Arrays oder Objekten, Getter und Setter, Generatoren oder Promises. Wer die neuen Features näher kennenlernen möchte, dem sei die Website es6katas.org empfohlen. Mithilfe von Katas kann man die Features direkt selbst ausprobieren.

ECMAScript 2015 wirbelte die JavaScript-Welt gründlich auf. Neue Fassungen der Sprache sollen seitdem jährlich und dafür mit geringerem Umfang erscheinen. Aus diesem Grund werden zur Versionierung nun Jahreszahlen verwendet. Letztes Jahr erschien so die wenig beachtete Ausgabe ECMAScript 2016. Die Neuerungen hielten sich tatsächlich stark in Grenzen: Neu eingeführt wurde die Array-Methode includes, die zurückliefert, ob ein Wert in einem Array vorhanden ist oder nicht. Das war zuvor nur umständlich über die indexOf-Methode möglich und brachte Probleme bei Elementen mit dem Wert NaN (not a number) mit sich.

> [NaN].indexOf(NaN) > -1
false

> [1, 2].includes(2)
true

Zweite Neuerung war der **-Operator zur Potenzierung, der sich auch bei Zuweisungen verwenden lässt.

> 2 ** 4
16

> let x = 3
> x **= 2
9

Das Erscheinen einer neuen JavaScript-Version bedeutet jedoch nicht zwangsläufig, dass alle Browserhersteller unverzüglich deren Implementierung liefern und ausrollen. Insbesondere bis die neuen Browser unter den Benutzern verteilt sind, gehen teilweise Jahre ins Land. Doch hier gibt es Abhilfe: Shims und Polyfills liefern Funktionen in älteren Browsern nach, die sich in diesen auf andere Weise abbilden lassen. Syntaxerweiterungen können mithilfe eines Build-Schritts in für ältere Browser verständliche Konstrukte umgewandelt werden. Diesen Vorgang nennt man dann Transpilation, angelehnt an den Begriff der Kompilierung. Ein bekannter Transpiler ist Babel. Dieser erlaubt es, das JavaScript von morgen bereits heute zu schreiben und in den derzeit verbreiteten Browsern einzusetzen.

Und auch 2017 steht eine neue Ausgabe auf dem Plan. ECMAScript 2017 führt unter anderem Operatoren aufs Feld, die .NET-Entwickler etwa seit 2012 kennen: async und await. Diese vereinfachen die Handhabung asynchroner Operationen beachtlich. In JavaScript stellen die asynchronen Operatoren syntaktischen Zucker über Promises dar, die ihrerseits das Problem der unrühmlichen Callback Hell in JavaScript lösten:

async function sayHello() {
const greeting = await fetch('https://example.com/greet.txt');
alert(greeting);
}

Bleibt aber noch die dynamische Typisierung als Eigenschaft der Sprache JavaScript, die bei falscher Handhabung gemeine Fehler erzeugen kann. Um statische Typisierung gerade auch im Hinblick auf die Implementierung großer Single-Page-Anwendungen im Web nachzurüsten, gab Microsoft die Programmiersprache TypeScript heraus. TypeScript stellt eine Übermenge von JavaScript dar und erlaubt die optionale Verwendung von Typen oder Zugriffsmodifikatoren. Zudem implementiert TypeScript neue und erfolgversprechende Sprachfeatures oftmals deutlich vor deren Übernahme in den offiziellen JavaScript-Sprachumfang. Analog zu Babel ist auch hier eine Source-to-Source-Kompilierung erforderlich. Im Gegenzug können Entwickler mit TypeScript bereits heute die asynchronen Operatoren async/await oder Dekoratoren einsetzen. Der Code, den der Anwendungsentwickler in TypeScript schreibt, ist verblüffend ähnlich zu C++, C# und Java. Mit dem Unterschied, dass sich das daraus entstehende JavaScript auf nahezu jeder Plattform ausführen lässt.

Mehr zu TypeScript folgt in der kommenden Woche. ()