Neue Sprachfeatures für JavaScript im ECMAScript-6-Entwurf – Teil 2

Promises und Template Strings

Ein weiterer Vorteil ist die verkürzte Schreibweise. Sie erlaubt, dass man die runden Klammern um die Parameter und die geschweiften Klammern um den Funktionsbereich optional entfallen lassen kann.

Im Umgang mit den Arrow-Funktionen gibt es drei Dinge zu beachten:

  • Sie lassen sich nicht als Konstruktor-Funktion verwenden. Es ist somit nicht möglich, sie mit new aufzurufen.
  • Der this-Kontext lässt sich nicht durch bind() oder apply verändern.
  • Das Standard-Argument arguments kann nicht für alle Parameter verwendet werden. Als Alternative kommen nur die erwähnten Rest-Parameter in Frage.

Es gibt ein paar gute Gründe, warum derartige Einschränkungen existieren; der wichtigste ist das lexikalische Binden des this-Kontext. Des Weiteren können die JavaScript-Laufzeitumgebungen den Umstand, dass nur noch benannte Parameter verwendet werden dürfen, dazu nutzen, die Ausführung zu optimieren. Ein weiterer Vorteil ist, dass sich diese Funktionen nicht mehr als Konstruktor verwenden lassen und man die JavaScript-Laufzeitumgebung durch die strikten Regeln verbessern kann.

Promises haben das Ziel, eine lange Verschachtelung von Callback-Aufrufen zu verhindern und somit den JavaScript-Quellcode lesbarer und damit wartbarer zu gestalten. Bibliotheken wie jQuery und AngularJS implementieren sie derzeit unterschiedlich. Da mit Promises/A+ bereits eine Spezifikation exisitiert, war eine Aufnahme in den ECMAScript-Standard eine notwendige und sinnvolle Folge. Das untenstehende Beispiel zeigt eine Umsetzung eines typischen Programmablaufs unter Einsatz von Callbacks, wobei sich Entwicklern, die eine andere Sprache gelernt haben, der Ablauf nicht sofort erschließt.

function timeout(name, duration, callback) {
let doTimeout = function() {
console.log("doTimeout "+ name + " aufgerufen.");
callback(null);
};

setTimeout(doTimeout, duration);
}

try {
timeout("to_1", 100, (err) => {
if (err) {
console.log(err);
} else {
timeout("to_2", 200, (err) => {
if (err) {
console.log(err);
} else {
timeout("to_3", 300, (err) => {
if (err) {
console.log(err);
} else {
console.log("callbacks erledigt ;-)");
}
});
}
});
}
});
} catch (err) {
console.log("Fehler: " + err);
}

Betrachtet man hingegen den folgenden Ausschnitt, ist der Ablauf auf den ersten Blick verständlich.

function timeout(name, duration) {
return new Promise((resolve, reject) => {
let doTimeout = function() {
console.log("doTimeout "+ name + " aufgerufen.");
resolve();
};

setTimeout(doTimeout, duration);
})
}

let p1 = timeout("to_1", 100);
let p2 = timeout("to_2", 200);
let p3 = timeout("to_3", 300);

Promise.all([p1, p2, p3])
.then(() => {
console.log("promises erledigt ;-)");
})
.catch((err) => {
console.log(err);
});

Eine für viele lange fällige Ergänzung des Sprachumfangs von JavaScript ist die Einführung von Vorlagenzeichenketten (Template Strings). Bisher war es in JavaScript schwierig, die Übersicht zu behalten, wenn eine verkettete Zeichenfolge mit vielen festen und variablen Teilen zu erstellen war. Mit ${name} kann man in Zukunft innerhalb einer Zeichenkette Variablen ansprechen. In den geschweiften Klammern ist es zudem möglich, komplette Ausdrücke inklusive Funktionsaufrufe unterzubringen:

var moment = require('moment');

let world = 'Welt';

// Erstellen eines zusammengesetzten Text nach dem alten Muster.
let text_old = 'Altes hallo ' + world;
console.log(text_old);

// Erstellen eines zusammengesetzen Textes mit Hilfe von Template-Strings.
let text_new = `Neues hallo ${world}`;
console.log(text_new);

let x = 1;
let y = 2;
let rechenergebnis = `${x} + ${y} = ${x+y}`;
console.log(rechenergebnis);

function GetZeitpunkt() { return new Date(); }
let zeitpunktAusgabe = `Es ist jetzt:
${moment(GetZeitpunkt()).format("HH:MM")}`;
console.log(rechenergebnis);