Angular. Ferdinand Malcher
Template-Strings können wir außerdem Ausdrücke direkt in einen String einbetten. Dafür gab es zuvor keine elegante Möglichkeit, und wir mussten stets Strings konkatenieren, um mehrere Zeichenketten zusammenzubringen.
const text = `Mein Name ist ${firstname}.
Ich bin ${age} Jahre alt.`;
const url = `http://example.org/user/${id}/friends?page=${page}`;
Listing 4–9 Template-String mit eingebetteten Ausdrücken
Wir werden Template-Strings mit Angular vor allem nutzen, um eine URL mit mehreren Parametern zusammenzubauen.
4.7Arrow-Funktionen/Lambda-Ausdrücke
Eine Arrow-Funktion ist eine Kurzschreibweise für eine normale function() in JavaScript. Auch die Bezeichnung Lambda-Ausdruck ist verbreitet.
Der rechtsseitige Ausdruck dient als Rückgabewert.
Die Definition einer anonymen function() verkürzt sich damit elegant zu einem Pfeil =>. Erhält die Funktion genau ein Argument, können die runden Klammern auf der linken Seite sogar weggelassen werden. Auch die geschweiften Klammern auf der rechten Seite können eingespart werden: Lässt man die Klammern weg, wird das Ergebnis des rechtsseitigen Ausdrucks als Rückgabewert für die Funktion verwendet. Wir müssen also kein return-Statement verwenden. Diese vier Definitionen sind gleichwertig:
function (foo) { return foo + 1; }
(foo) => { return foo + 1; }
foo => { return foo + 1; }
foo => foo + 1;
Damit können anonyme Funktionen mit nur wenig Tipparbeit definiert werden. Das folgende Beispiel zeigt, wie wir alle geraden Zahlen aus einer Liste ermitteln können. Zuerst wird eine herkömmliche Funktionsdeklaration verwendet, wie wir sie aus ES5 kennen. Die Arrow-Funktion im zweiten Beispiel ist allerdings wesentlich kompakter: Es ist möglich, einen einzeiligen Ausdruck einzusetzen, um die Funktion zu deklarieren.
const numbers = [0, 1, 2, 3, 4];
const even1 = numbers.filter(
function(value) {
return value % 2 === 0;
}
);
const even2 = numbers.filter(
value => value % 2 === 0
);
Listing 4–10 Herkömmliche Callback-Funktion
Bei komplexerer Logik kann auch ein mehrzeiliger Block verwendet werden. In diesem Fall muss der Rückgabewert allerdings mit return aus der Funktion herausgegeben werden.
this-Kontext
Ein weiterer Vorteil der Arrow-Funktion ist, dass sie keinen eigenen this-Kontext besitzt. Mit der normalen function() ist es oft erforderlich, this in einer temporären Variable zu speichern, um in einer Callback-Funktion überhaupt darauf zugreifen zu können. Mit Arrow-Funktionen existiert dieses Problem nicht, denn die Variable this wird stets aus dem übergeordneten Kontext verwendet. Dies entspricht genau dem, was man beim Programmieren mit Klassen gemeinhin benötigt.
class User {
firstname: string;
friends: User[];
showFriends() {
const self = this;
this.friends.forEach(function(friend) {
console.log(`${self.firstname} kennt ${friend.firstname}`);
});
}
}
Listing 4–11 Zusätzlicher Code durch die Verwendung herkömmlicher Callback-Funktionen
Dieser unschöne Zwischenschritt entfällt, wenn eine Arrow-Funktion verwendet wird.
class User {
// ...
showFriends() {
this.friends.forEach(friend => {
console.log(`${this.firstname} kennt ${friend.firstname}`);
});
}
}
Listing 4–12 Vereinfachung: Arrow Functions werden im Kontext der jeweiligen Klasse ausgeführt.
4.8Spread-Operator und Rest-Syntax
Der Spread-Operator erleichtert den Umgang mit Arrays, Objekten und Argumenten von Funktionen. Mithilfe der Syntax können Teile eines Objekts oder Arrays expandiert werden, um
mehrere Elemente in ein Array zu kopieren,
mehrere Eigenschaften in ein Objekt zu kopieren oder
mehrere Argumente bei Funktionsaufrufen anzugeben.
Praktisch verwenden wir den Spread-Operator vor allem, um Objekte und Arrays zu klonen. Das wollen wir uns an ein paar Beispielen anschauen.
Spread-Operator vs. Spread-Syntax
Genau genommen ist der Spread-Operator kein Operator, sondern eine Syntax – »Operator« klingt aber viel besser. Die beiden Bezeichnungen sind also gleichbedeutend.
Objekteigenschaften kopieren
Wir gehen von der folgenden Problemstellung aus: Es existiert ein Objekt myObject. Wir wollen davon eine Kopie erzeugen und die Kopie verändern. Das originale Objekt soll dabei natürlich unverändert bleiben.
Auf den ersten Blick scheint diese Aufgabe einfach zu sein. Wir weisen das Objekt einer neuen Variable copy zu und ändern die Eigenschaft year. Bei der Ausgabe sehen wir allerdings, dass diese Herangehensweise nicht funktioniert …
const myObject = { title: 'Angular', year: 2016 };
const copy = myObject;
copy.year = 2020;
console.log(copy); // { title: 'Angular', year: 2020 }
console.log(myObject); // { title: 'Angular', year: 2020 }
Referenzen auf Objekte und Arrays
Um den Fehler zu verstehen, muss man Folgendes wissen: Variablen mit Objekten oder Array enthalten stets nur die Referenz auf das Objekt, nicht das Objekt selbst. Die beiden Variablen myObject und copy zeigen also auf dieselbe Speicherstelle. Ändern wir etwas an den Daten, wird das originale Objekt im Speicher überschrieben.
Object.assign()
Lange Zeit war deshalb die Methode Object.assign() das Mittel der Wahl, um Objekte ineinanderzukopieren. Mit dem Spread-Operator können wir die Aufgabe allerdings viel eleganter lösen:
const myObject = { title: 'Angular', year: 2016 };
const copy = { ...myObject, year: 2020 };
console.log(copy);