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

Transpiler, weitere Neuerungen

Über Umwege zum Code

Da seit einiger Zeit die Notwendigkeit besteht, Enterprise-Anwendungen beziehungsweise komplexere Bibliotheken für JavaScript zu entwickeln, entstanden einige Sprachen, um die Entwicklung von JavaScript zu vereinfachen. Die geläufigsten unter ihnen sind CoffeeScript, TypeScript und Dart. Sie stellen Abstraktionen von JavaScript dar, und ein Transpiler übersetzt ihre Syntax in JavaScript, sodass jeder Browser und jede andere auf das Ausführen von JavaScript ausgelegte Umgebung damit arbeiten kann. Von Google gibt es alternativ eine spezielle Version von Chrome, die in der Lage ist, Dart direkt auszuführen.

Wenn man die JavaScript-Abstraktionssprachen, im speziellen TypeScript, betrachtet, findet man viele Analogien zur kommenden JavaScript-Version. Microsoft ist maßgeblich an der Standardisierung von ECMAScript 6 beteiligt und hat TypeScript bewusst an ihr angelehnt. Auch bei Dart finden sich einige Ähnlichkeiten zum kommenden ECMAScript-Standard wieder, zum Beispiel Klassen und Vererbung. Die Verwandschaft zur CoffeeScript-Syntax ist nicht so groß, wenngleich Konzepte wie Spreads in ECMAScript 6 übernommen wurden.

Unter dem Namen Traceur gibt es bereits einen Transpiler (Compiler, der Quellcode von einer Programmiersprache in eine andere überführt) von ECMAScript-6- zu JavaScript-Code, der zu ECMAScript Version 3 oder 5 kompatibel ist. Die Entwickler von Traceur sind dabei bemüht, den Transpiler weiter voranzutreiben, sodass er bald den gesamten Sprachumfang unterstützt, soweit dies ohne Erweiterung der JavaScript-Laufzeitumgebung möglich ist. Alle Beispiele dieses Artikels sind – mit Ausnahme des WeakMap-Beispiels – mit Traceur übersetzt worden, was beweist, dass Traceur schon die wichtigsten ECMAScript 6-Features unterstützt.

Das folgende Codebeispiel zeigt, wie man eine ECMAScript-6-Datei mit Traceur übersetzt:

'use strict';

var traceur = require('traceur');
var path = require('path');

// Verwendung der als exprimentell gekennzeichneten Funktionen
traceur.options.experimental = true;

traceur.require.makeDefault(function(filename) {
// Ausnahmen definieren.
if (filename.indexOf("node_modules") != -1) {
return false;
}

// require aus node.js fuer alle anderen Dateien ueberschreiben
return true;
});

if (process.argv.length === 3) {
var filename = process.argv[2];

if (filename.indexOf("./") !== 0) {
filename = "./" + filename;
}

// Laden der JavaScript-Datei
require(filename);
} else {
console.log("ERROR: ");
console.log(" using " + path.basename(__filename) +
" <filename to use>.");
console.log("");
console.log(" sample: " + path.basename(__filename) +
"variables/sample_let.js");
process.exit();
}

Selbst bekannte Bibliotheksentwickler setzen ECMAScript 6 heute unter Verwendung von Traceur ein. Das bekannteste Beispiel dürfte Angular.js 2.0 sein. Diese Version soll vollständig in ECMAScript 6 implementiert werden. Da sie zusätzlich modularer aufgebaut sein wird, steht das AngularJS-Modul für Dependency Injection schon heute für den privaten Einsatz zur Verfügung. Damit zeigt sich, dass das neue ECMAScript bereits in der Praxis zum Einsatz kommt.

Weitere neue Funktionen

ECMAScript 6 enthält eine ganz Fülle von Neuerungen, sodass hier nicht alle im Detail abgehandelt werden können. Einige sollen jedoch an dieser Stelle noch Erwähnung finden:


  • Das Math-Objekt wird um neue Funktionen wie IsInteger() und IsNaN() erweitert.
  • Das Array-Objekt bietet nach der Aktualisierung zahlreiche neue Methoden wie entries(), keys(), values() und findIndex().
  • Das Destructuring bietet eine vereinfachte Syntax, um ein Array in seine Elemente aufzusplitten und eine Zuweisung an Variablen durchzuführen.
  • Proxies ermöglichen Wrapper, um bestehende Typen, zum Beispiel zu überwachen oder Logging und Profiling durchzuführen. Entwickler können aus einer Palette von Funktionen wählen, um gezielt Aufrufe des "gewrappten" Objekts an den Proxy umzuleiten.
  • Die Reflect API dient der Ermittlung von Meta-Daten eines Objekts, wie es in den gängigen Hochsprachen wie C# und Java bereits möglich ist.
  • Die Unterstützung von Unicode wird soweit ausgebaut, dass der globaler Einsatz einer Anwendung möglich wird. Die wichtigsten Erweiterungen sind Unicode-Literale in Strings und die Ergänzung der regulären Ausdrücke um ein Flag zum korrekten Umgang mit Unicode-Zeichen.
  • Das Schlüsselwort const bietet die Möglichkeit, Variablen als nicht veränderbar zu definieren. Eine erneute Zuweisung würde zu einem Laufzeit-/Compiler-Fehler führen.
  • Binary und Octal Literals ermöglichen binäre und oktale Zahlendarstellung im Quellcode.
  • Die meisten heutigen JavaScript-Laufzeitumgebungen sind nicht sehr robust beim Umgang mit tief geschachtelten rekursiven Funktionen, wie sie üblicherweise im mathematischen Umfeld nötig sind. ECMAScript 6 bietet für sogenannte "Tail Calls" eine verbesserte Verarbeitung, die tiefergehende Rekursionen ermöglicht.