ECMAScript 6 - Javascript, Frau blickt in Zukunft

ECMAScript 6 – die Zukunft von JavaScript?

JavaScript (JS) ist seit Jahren ein alltäglicher Begleiter von Web Entwicklern, sei es nun im Frontend oder Backend. Als Skriptsprache für den Browser groß geworden, wird JavaScript auch für andere Anwendungsbereiche genutzt, wie z. B. Node.js.

Auch für uns ist die Arbeit mit JavaScript ein wichtiger Bestandteil des Berufslebens. Zum Beispiel setzt Shopware 6 für die Administrationsoberfläche im Backend auf das Framework Vue.js. Im Frontend wird nach dem Ansatz „auf jQuery zu verzichten“ gearbeitet und wenn möglich alles in reinem JavaScript, „Vanilla JavaScript“, umzusetzen. Dank des Standards ECMAScript 6 oder kurz ES6 und dessen Updates bietet die Programmiersprache interessante Funktionen, die die Arbeit erleichtern.

Was ist ECMAScript?

ECMAScript beschreibt den Standard für JavaScript. So unterstützen alle modernen Browser seit 2012 die Version 5.1. Auf die Version 6 und deren Nachfolger, die jedes Jahr ein Update erhalten, werden wir heute einen Blick werfen. Das Problem bei der Arbeit mit den neuen Funktionen ist, dass einige Browser eventuell noch nichts mit den Spezifikationen anfangen können. Es lohnt sich, einen Blick auf die Browserkompatibilität zu werfen. Wenn für ein Kundenprojekt z. B. klar ist, dass der Fokus auch auf dem Internet Explorer 11 liegt, muss eine Alternative zum modernen JavaScript geschaffen werden.

Durch Babel ist es möglich, ein für alle Browser kompatibles JavaScript zu kompilieren. Vor allem für Versionen von ECMAScript 2015 und modernerer Varianten kann das sinnvoll sein. Bei der Entwicklung eines Shopware 6 Projektes kann das geschriebene JS dank eines eingebauten Compilers auch direkt in für ältere Browser verständlichen Code umgewandelt werden. Sehr cool! Um nicht den Rahmen zu sprengen, werde ich hier nicht auf die Einrichtung von Babel eingehen.

Praktische Beispiele

Am einfachsten ist es, die Vorteile von ES6 zu verdeutlichen, wenn ich es an einigen Beispielen demonstriere. Wer bereits Erfahrung mit der Version von JS hat, dürfte nicht viel Neues erfahren, da es sich hier nur um einen kleinen Überblick handeln soll. Genug der Worte, los geht’s!

let und const

Schluss mit Variablen, die unerwünscht überschrieben werden konnten. Dank des Keywords let ist die Variable im block scope. Ein Block ist z. B. eine If-Schleife. Früher konnte eine mit var deklarierte Variable in einer Schleife auch außerhalb dieser aufgerufen werden. Nun bleibt die in einem Block erstellte Variable außerhalb dieses Blocks „verborgen“. Let überschreibt auch keine Variablen außerhalb des Blocks, die den gleichen Namen haben.

var a = 0;
console.log(a);
if (condition) {
  let a = 1;
  console.log(a);
}
console.log(a);

// 0
// 1
// 0

if (condition) {
  let a = 'test';
  console.log(a);
}
console.log(a);

// test
// Uncaught ReferenceError: a is not defined

Es gibt eine weitere Variante, Variablen zu deklarieren. Mit const kann eine Konstante erschaffen werden, die nicht neu zugewiesen werden kann. Ansonsten verhält sich const genauso wie let, ist also block scoped.

Arrow functions

Funktionen bekamen mit den neuen arrow functions eine alternative Syntax. Dabei kann das function und return Keyword weggelassen werden und auch die geschweiften Klammern. Dies ist jedoch nur der Fall, wenn die Funktion nur einen Parameter besitzt und der Funktionsinhalt nur einen Wert zurückgibt. Was beachtet werden muss, arrow functions haben nicht ihr eigenes this. Außerdem sind sie nicht vom hoisting betroffen, das heißt sie müssen definiert werden bevor diese aufgerufen werden.

// old syntax
let greeting = function(name) {
    console.log(`Hello ${name}!`);
}

// new syntax
let greeting = (name) => {
    console.log(`Hello ${name}!`);
}

// new syntax 
// omit parenthesis if only one parameter exists 
// omit return keyword if statement has only return expression
let doubleValue = value => value*2;
console.log(doubleValue(42));

Klassen in ECMAScript

Mit ES6 wurden Klassen als Templates für JavaScript Objekte eingeführt. Der große Vorteil ist, dass die neue Syntax eingängiger und einfacher zu verstehen ist. Mithilfe von class werden Klassen erstellt. Außerdem benötigt die Klasse eine constructor Methode, die automatisch aufgerufen wird, wenn ein neues Objekt erstellt wird. Wird keine constructor Methode angegeben, dann fügt JS einen leeren constructor hinzu. Klassenmethoden werden mit der gleichen Syntax wie Objektmethoden definiert.

class Pokemon {
    constructor(name, type) {
        this.name = name;
        this.type = type;
    }
}

let pikachu = new Pokemon("Pikachu", "Electric");

Default Parameter

Endlich! In JS ist es möglich einen Standardwert für Parameter zu definieren. Anstelle einer zusätzlichen Abfrage in der Funktion kann nun wie z. B. in PHP ein Default Parameter angeben werden. Es entfällt das lästige Prüfen, ob tatsächlich ein Parameter existiert.

// old version
function multiply(factorOne, factorTwo) {
    factorTwo = (typeof factorTwo !== 'undefined') ?  factorTwo : 1;
    return factorOne * factorTwo;
}

// new version
function multiply(factorOne, factorTwo = 1) {
    return factorOne * factorTwo;
}

Ein Versprechen wird nicht gebrochen: Promises

Promises funktionieren ähnlich wie Versprechen im wahren Leben. Bei einem Versprechen wird eine Aussage für die Zukunft getroffen. Diese sollte zutreffen, kann aber eben durch veränderte Umstände auch nicht eintreffen. Das gilt auch für Promises in JS. Solange ein Promise nicht aufgelöst wurde, ist der Status pending. Konnte das Versprechen eingehalten werden, ist er resolved und wenn nicht, dann ist der Staus rejected. Als Beispiel dient eine Anfrage an einen Server. Solange die Anfrage läuft, ist diese pending und falls die gewünschten Daten zurückkommen, wird das Promise resolved. Promises sind also Objekte, die das Ergebnis von asynchronen Aktionen zurückgeben, wenn das Versprechen gehalten wurde. Falls dies nicht der Fall ist, wird auf einen Fehler aufmerksam gemacht.

Promises werden mit dem Konstruktor new Promise erzeugt und enthalten eine Funktion als Parameter. Diese hat die Variablen resolve und reject als Parameter. Wenn eine Aktion als erfolgreich angesehen wird, dann wird resolve ausgeführt, andernfalls reject. An ein Promise kann nun then und catch angehangen werden, um einen der beiden genannten Fälle abzufangen. Schauen wir uns ein Beispiel im Code an.

const myPromise = new Promise((resolve, reject) => {  
    // some functionality
    // api calls or something
    
    if (condition) {    
        resolve('Promise is resolved successfully');  
    } else {    
        reject('Promise is rejected');  
    }
});

// if promise is resolved true then function is called otherwise catch
myPromise.then((message) => { 
    console.log(message);
}).catch((message) => { 
    console.log(message);
});

Warten mit Async/Await

Mit der 2017er Version von ECMAScript gab es eine weitere Verbesserung in der asynchronen Programmierung in JavaScript. Dafür wird eine Funktion mit dem async Keyword gekennzeichnet. Eine Funktion würde in diesem Fall z. B. keinen Wert zurückgeben, sondern ein Promise. Das Ergebnis kann erst in Zusammenhang mit dem await Keyword gesehen werden. Await kann nur in einer Funktion, die mit async definiert wurde, genutzt werden. Erreicht der Code die Stelle mit dem await, wird solange gewartet bis es einen Rückgabewert gibt. Erst danach geht es weiter. Für weitere Informationen empfehle ich diesen Artikel.

function waitASecond(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 1000);
  });
};

let add = async function(x) { // async function expression assigned to a variable
  let a = await waitASecond(10); // waits until waitASecond finished
  return x + a + b;
};

add(100).then(v => {
  console.log(v);  // prints 110 after 1 second.
});

Template-Strings

Strings in JavaScript zusammenzusetzen, kann zu einer nervigen Aufgabe werden. Vor lauter Plus- und Anführungszeichen leidet die Lesbarkeit.

console.log('Hello' + someNameVariable + '! Today is ' + someDateVariable + '.');

Besser wäre es, Variablen direkt im String zu verwenden oder? Dafür gibt es die Template-Strings oder template literals. Der String wird ganz einfach von Backticks („) umschlossen. Darin können nun Variablen durch die Syntax $(variablenName) genutzt werden. Bye bye, Pluszeichen.

console.log(`Hello ${someNameVariable}! Today is ${someDateVariable}.`);

Destructuring

Es ist nun einfacher, Arrays und Objekte auseinanderzunehmen. Variablen können Werte aus Arrays oder Objekten simpel zugeordnet werden. Um es einfach zu erklären, gibt es hier ein Beispiel aus dem Code von Shopware.

// Component is qual to Shopware.Component and Mixin to Showpare.Mixin
const { Component, Mixin } = Shopware;

Dabei enthält das Objekt Shopware Component und Mixin. Diese können dank des Destructurings ohne viel Code direkt in eine Variable gespeichert werden.

Fazit

Das war vielleicht schon eine ganze Menge, aber noch lange nicht alles. Ich habe mit den Informationen nur an der Oberfläche gekratzt. ES6 und alle weiteren Updates brachten viele spannende Neuerungen in die JavaScript-Welt. Funktionen wie includes, isNaN oder Spread und Rest Operator sind nur weitere Möglichkeiten, die genutzt werden können und den Arbeitsalltag erleichtern.

Wer Lust bekommen hat mehr über das Thema zu erfahren, kann gerne den unten aufgeführten Quellen folgen und das Wissen vertiefen.

Kommentar hinzufügen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert