Unterschiede zwischen normalen Funktionen und Arrow Functions in JavaScript – und wann man welche Syntax verwenden sollte
(jrsinclair.com)- Funktionsdeklarationen in JavaScript können auf verschiedene Arten erfolgen, etwa als Deklaration mit dem Schlüsselwort
function, als Funktionsausdruck oder als Arrow Function - Für Funktionsdeklarationen gilt Hoisting, sodass sie an jeder Stelle im Code referenziert werden können
- Arrow Functions punkten mit einer knappen Syntax, haben aber wichtige Unterschiede wie keine eigene this-/arguments-/super-Bindung
- Für Konstruktorfunktionen, Generatoren und Methoden sind Arrow Functions nicht geeignet
- Für einfache Callbacks oder anonyme Funktionen sind Arrow Functions besser geeignet
Function Declarations, Function Expressions, and Arrow Functions
- In JavaScript kann man Funktionen auf drei Arten definieren: als Funktionsdeklaration (Statement), Funktionsausdruck (Expression) und Arrow Function
- Eine Funktionsdeklaration bindet den Namen direkt, wie in
function isVowel(chr) { ... }, und kann überall im Code referenziert werden (Hoisting). In Stack Traces und beim Debugging wird der Funktionsname klar angezeigt - Ein Funktionsausdruck weist einer Variablen eine anonyme Funktion zu, etwa
const takeWhile = function(predicate, arr) { ... } - Auch Funktionsausdrücke können intern einen Namen haben, aber dieser Name wird nicht an den äußeren Scope gebunden und dient hauptsächlich der Fehlerverfolgung in Stack Traces
Hoisting and Naming
- Funktionsdeklarationen werden von der JavaScript-Engine gehisst (hoisted), sodass sie auch vor ihrer Deklaration aufgerufen werden können
- Anonyme Funktionsausdrücke können erst nach der Zuweisung an die Variable aufgerufen werden
- Für das Debugging kann es hilfreich sein, Funktionen explizit einen Namen zu geben, da dies in Stack Traces Vorteile bringt
Arrow Functions
- Kurze und kompakte Syntax: geschrieben ohne das Schlüsselwort
functionin der Form(Parameter) => { ... } - Sind immer anonyme Funktionen (können aber durch Zuweisung an eine Variable wie benannt verwendet werden)
- Können nur als Expression verwendet werden, nicht als Statement
- Keine eigene this-/arguments-/super-Bindung: Anders als Funktionsdeklarationen oder Funktionsausdrücke übernehmen sie das this des äußeren Scopes
- Bei einem einzelnen Ausdruck können geschweifte Klammern und
returnweggelassen werden; bei genau einem Parameter auch die Klammern - Nicht als Konstruktor verwendbar: Arrow Functions können nicht mit dem Schlüsselwort new aufgerufen werden und funktionieren nicht als Konstruktorfunktionen
- Keine Generatoren: yield kann nicht verwendet werden, sie lassen sich nicht als Generatorfunktion definieren
- Codebeispiel:
const sum = (a, b) => a + b; const square = x => x * x;
Praktisches Beispiel: this, Konstruktoren und Generatoren
- Es wird ein Beispiel für den Unterschied im Umgang mit
thiszwischen normalen Funktionen und Arrow Functions gezeigt- Wird eine normale Funktion als Methode in einem Objekt verwendet, zeigt
thisauf das Objekt selbst; bei einer Arrow Function zeigt es aufundefinedoder auf dasthisdes äußeren Scopes
- Wird eine normale Funktion als Methode in einem Objekt verwendet, zeigt
- Definiert man eine Konstruktorfunktion als Arrow Function, führt das zu einem
TypeError - Generatorfunktionen müssen zwingend mit der Syntax
function*geschrieben werden
Welche Funktionssyntax sollte man wann wählen?
- Generatoren (
yieldverwenden) nötig →function*verwenden thismuss genutzt werden → Schlüsselwortfunctionoder Klassenmethode verwenden- Hoisting wird benötigt oder eine besser sichtbare Struktur auf höherer Ebene ist gewünscht → Funktionsdeklaration verwenden
- Trifft nichts davon zu → zur Arrow Function greifen, um knapper zu schreiben
Fazit
- In JavaScript sollte die Funktionssyntax je nach Einsatzzweck, Bedarf an
thissowie je nach Konstruktor- oder Generatorverwendung gewählt werden - Für alltägliche Callbacks und einfache Funktionen sind Arrow Functions die beste Wahl
- Für Objektmethoden, Konstruktoren und Generatoren sollte die
function-Syntax verwendet werden - Wenn Hoisting oder mehr Freiheit bei der Reihenfolge der Deklaration nötig ist, ist die Funktionsdeklaration vorteilhaft
3 Kommentare
So grundlegend wie die Frage, ob ein
prototypevorhanden ist, ist auch ...auch die Art, auf die Referenz der erzeugten Higher-Order-Funktion zuzugreifen, ...
const a = (a: () => null): (() => () => null) =>() => a() => ❤️