brainbits Blog

ECMAScript 2015: Was hat sich für uns bewährt?

Steven Weingärtner25.08.2016Anwendungsentwicklung • Code • Frontend
ECMAScript 2015 - Praxistest

ECMAScript 2015 (inoffiziell auch ECMAScript 6 genannt) ist die neue Version des Standards, der der Sprache JavaScript zugrunde liegt. Bisher gab es für diesen Standard nur relativ selten Updates, weswegen es bei JavaScript kaum Fortschritte gab. Nun will TC39, die Arbeitsgruppe hinter JavaScript, den Standard jedes Jahr ein wenig erweitern. Das erste Resultat, eben ECMAScript 2015, haben wir vor über einem halben Jahr erstmals in einem unserer Projekte eingesetzt. Für alle Interessierten haben wir hier ein kleines Fazit unserer Erfahrungen gezogen.

Unser Setup

ECMAScript 2015 bekam als erste Version der versprochenen Welle an Updates ein großes Set von Features spendiert. Doch leider sind noch nicht alle Features in allen Browsern angekommen, so dass man entweder auf einiges verzichten oder einen Transpiler einsetzen muss, der die Features in abwärtskompatiblen ECMAScript5-Code umwandelt.

Wir setzen zu diesem Zweck auf den pluginbasierten Transpiler Babel . Dadurch können wir viele der neuen Features einsetzen, ohne auf die Browserkompatibilität zu verzichten. Darüber hinaus unterstützt Babel über entsprechende Plugins auch Features, die es noch gar nicht in den offiziellen Standard geschafft haben (z. B. decorator oder class properties). Babel kann dann über ein Konsolenkommando oder direkt aus Webpack oder Browserify benutzt werden.

Features, die sich für uns bewährt haben

Im Folgenden haben wir die Features gesammelt, die sich in unserem Alltag als besonders nützlich erwiesen haben und auf die wir nicht mehr verzichten wollen würden.

Klassen

ECMAScript 2015 macht es einem leichter, “Klassen” und einfache Objekte zu definieren. Nun ist nicht jeder Entwickler ein großer Freund von Klassen in JavaScript, schließlich basiert JavaScript als objektorientierte Sprache auf einer gänzlich anderen Herangehensweise als Sprachen, die von Grund auf Klassen beinhalten. Trotzdem gibt es einige Anwendungsfälle, die nun einfacher geworden sind.

class Counter extends Component {
    state = {
        count: 0,
    }
    handleClick() {
        this.setState({
            count: this.state.count++,
        });
    }
    render() {
        // ...
    }
}

Dabei sind Klassen nichts weiter als Funktionen, die nur über das Keyword “new” aufgerufen werden dürfen und deren Methoden an den Prototyp der Funktion gehängt werden. Klassen bringen damit zwar kein wirklich neues Feature, der Code wird dadurch aber viel übersichtlicher und meistens kürzer.

Neue Funktions-Features

In JavaScript benutzt man sehr häufig anonyme Inline-Funktionen, also Funktionen, die keinen Namen haben und nur an einer bestimmten Stelle verwendet werden. ECMAScript 2015 hat für diese Funktionen eine Kurzschreibweise (“arrow function”) eingeführt, die besonders bei kurzen, einzeiligen Funktionen zur Geltung kommen:

const userList = [
    {id: 1, name: 'Max'},
    {id: 2, name: 'Maria'},
    {id: 3, name: 'Michael'},
    {id: 4, name: 'Steven'},
];
userList
    .filter(user => user.id !== 1)
    .map(user => user.name)
    .forEach(userName => console.log ('Hallo ' + userName));

Weiterhin behalten arrow functions den “thisscope” der Funktion, in der sie definiert werden.

Besonders wenn man mit Objektinstanzen arbeitet, erspart dies viele vorher benötigte “self”- Variablen oder “bind”-Aufrufe im Code.

class ToggleButton {
    _addEventListeners() {
        this.element.addEventListener('click', () => this.active = !this.active);
    }
    // …
}

Außerdem ist es nun endlich möglich, Standardwerte für Funktionsparameter zu definieren.

function raiseAge(user, ageDiff = 1) {
    user.age += ageDiff;
}

Template Strings

Bisher durften in JavaScript Strings nicht über mehrere Zeilen gehen. Daher war es immer mühselig, wenn man mit verschiedenen Anführungszeichen arbeiten musste oder in einem langen String Variablen einsetzen wollte. Jetzt kann man mit einfachen “backticks” einen Template String markieren, der mehr Möglichkeiten birgt als einfache Strings.

const name = 'Michael';
const welcome = `
    <h1>Herzlich Willkommen '${name}'</h1>
    <p class = "intro">Schön dich zu sehen!</p>
`;

Verkürzte Objekt-Schreibweise

Auch Objekte bekommen eine vereinfachte Schreibweise. Zum einen können Methoden in derselben Schreibweise wie bei Klassen definiert werden, zum anderen kann man den Eigenschaftsnamen bei einer Zuweisung weglassen, wenn dieser dem verwendeten Variablennamen entspricht. Außerdem gibt es nun eine Möglichkeit, “dynamische” Eigenschaftsnamen direkt bei der Erzeugung eines Objekts anzugeben.

const prefix = 'Mr.';
const name = 'Michael';
const optimist = true;
const user = {
    id: 1,
    name,
    [optimist ? 'isYoung' : 'isOld']: true,
    getPrefixedName() {
        return `${prefix} ${name}`;
    },
};
// Resultat: {name: 'Michael', isYoung: true, getPrefixedName: function...}

Auch diese Schreibweisen dienen vor allem der Übersichtlichkeit - besonders, wenn man bestehende Variablen in ein Objekt verpacken will, um sie als Rückgabewert einer Funktion oder als Parameter für ein Event zu verwenden.

Spread und Rest Operator

Mit diesem Feature kann man gleich mehrere Probleme auf einmal lösen. Egal ob man die Werte eines Arrays als einzelne Parameter an eine Funktion übergeben oder zwei Arrays miteinander kombinieren möchte – beides lässt sich nun noch einfacher realisieren als bisher.

const moreUsers = [
    ...users,
    {id: 5, name: 'Patrick'},
];
register(...moreUsers);

Doch auch beim Annehmen einer beliebigen Anzahl von Parametern in einer Funktion wird es nun einfacher – dank des “Rest Operators”.

function register(firstUser, ...otherUsers) {
    // do something with users
}

Destructuring

Es ist nicht nur einfacher geworden, Eigenschaften in ein Objekt zu schreiben,  sondern auch, Eigenschaften aus einem Objekt herauszuholen - durch Object Destructuring.

Dabei kann man relativ einfach bestimmte Eigenschaften eines Objekts oder Elemente eines Arrays direkt in Variablen schreiben.

const [max,, michael, ...rest] = users;
const {id, name, isOld = false} = michael;

Dieses Feature erlaubt es, viele einzelne Zuweisungen zu kombinieren und so zu vereinfachen: Weniger Code, mehr Übersicht.

Module

Das wohl wichtigste Thema haben wir für das Ende aufgespart. Erstmals gibt es ein offizielles Modulsystem für JavaScript. Bisherige Lösungen wie CommonJS oder RequireJS werden so auf absehbare Zeit abgelöst und durch diese native Lösung ersetzt.

Derzeit müssen die Module noch mit einem Tool wie Webpack oder Browserify zusammengefasst werden, um im Browser zu funktionieren. Wenn aber die Browser diesen Standard implementiert haben, kann man (gerade im Hinblick auf HTTP2) viele Vorteile daraus ziehen.

Bislang haben wir CommonJS als Modulsystem eingesetzt. Das neue ECMAScript-Modulsystem ist damit verglichen sprechender und flexibler. Ein Modul wird dadurch definiert, dass es etwas exportiert wie zum Beispiel Funktionen, Konstanten oder Klassen. Dieses Modul kann dann an anderer Stelle – zum Beispiel einem zweiten Modul – wieder importiert werden.

// Datei: functions.js
export function register () {
    // ...
}
// Datei: main.js
import {register} from './functions.js';
register();// Datei: functions.js
export function register () {
    // ...
}
// Datei: main.js
import {register} from './functions.js';
register();// Datei: functions.js
export function register () {
    // ...
}
// Datei: main.js
import {register} from './functions.js';
register();// Datei: functions.js
export function register () {
    // ...
}
// Datei: main.js
import {register} from './functions.js';
register();

Es gibt viele verschiedene Möglichkeiten, Code zu exportieren oder zu importieren, aber alle folgen einem ähnlichen Muster. Durch dieses Modulsystem gibt es endlich einen Standard, an den sich mittelfristig alle Entwickler von Bibliotheken halten sollten, um so die aktuelle Fragmentierung in CommonJS, RequireJS sowie in Modulen, die globale Variablen nutzen, zu beenden.

Was ist mit ECMAScript 2016?

Die Liste der Erweiterungen in ECMAScript 2016 ist sehr kurz. Das ist bewusst so, führt aber dazu, dass wir die neuen Features dieser Nachfolgeversion bisher noch nicht angewendet haben. Allerdings halten wir stets die Augen offen nach Fällen, in denen auch diese neuen Features sinnvoll zum Einsatz kommen können.

Fazit

Wir haben mit diesem Artikel nur die Spitze des Eisbergs berührt. ECMAScript 2015 hat eine sehr lange Liste an neuen Features. Für viele Features benötigt man noch einen Transpiler oder einen Polyfill. Manche Features lassen sich nicht einmal durch solche Hilfsmittel in allen aktuellen Browsern einsetzen. Trotzdem hat sich der Umstieg für unsere JavaScript-Projekte bewährt. Die meisten Features dienen zwar „nur“ der Übersichtlichkeit des Codes und bringen keine wirklich neuen Funktionen, doch gerade diese Features verbessern die Qualität moderner Anwendungen und machen den Code wartbarer. Jede Zeile Code, die eingespart wird, ist eine Zeile, die keinen Fehler verursachen kann.

Zurück zur Übersicht