Start · Sprachen · JavaScript · Kapitel · Funktionen & Closures
// Kapitel · JavaScript

Funktionen & Closures

Diese Sektion behandelt die Syntaxformen von Funktionen in JavaScript, also Deklaration, Ausdruck und Arrow Function, dazu Parameter-Features und Closures. Außerdem geht es um typische Fallstricke mit Gültigkeitsbereich und this.

In JavaScript sind Funktionen normale Werte. Du kannst sie Variablen zuweisen, als Argument übergeben und aus anderen Funktionen zurückgeben. Eine Closure entsteht, wenn eine Funktion Variablen aus dem Bereich verwendet, in dem sie definiert wurde. Diese Variablen bleiben erhalten, auch wenn die äußere Funktion schon beendet ist.

Deklaration, Ausdruck, Arrow Function

Funktionsdeklarationen werden gehoistet. Du kannst sie also schon vor ihrer Definition aufrufen. Bei Funktionsausdrücken und Arrow Functions geht das nicht. Arrow Functions haben außerdem kein eigenes this und kein arguments.

function add(a, b) { return a + b; }
const mul = function (a, b) { return a * b; };
const square = (x) => x * x;          // impliziter Rückgabewert
const toObj = (id) => ({ id });       // Objektliteral in Klammern!

Parameter: Defaults, Rest, Destrukturierung

Standardwerte greifen nur bei undefined, nicht bei null. Rest-Parameter sammeln die übrigen Argumente in einem echten Array.

const greet = (name = 'Welt', ...rest) =>
  `Hallo ${name}! (${rest.length} weitere)`;

const connect = ({ host = 'localhost', port = 80 } = {}) =>
  `${host}:${port}`;

connect({ port: 8080 }); // "localhost:8080"
connect();               // "localhost:80"

Closures

Die innere Funktion behält eine Referenz auf die Variablen der äußeren, keine Kopie. So lässt sich privater Zustand ohne Klassen umsetzen:

const createCounter = (start = 0) => {
  let count = start;
  return {
    inc: () => ++count,
    reset: () => { count = start; },
  };
};

const counter = createCounter();
counter.inc(); counter.inc(); // 2
// count ist von außen nicht erreichbar

Closures sind auch die Grundlage von Callbacks, Event-Handlern, Memoisierung und Currying.

Fallstricke

  • var in Schleifen: Alle Closures teilen sich dieselbe Variable. Mit let bekommt jeder Durchlauf eine eigene Bindung.
  • Arrow Functions als Methoden: this zeigt dann nicht auf das Objekt. Nutze dafür die Methodenkurzschreibweise obj = { run() { … } }.
  • Speicher: Closures halten referenzierte Objekte am Leben. Entferne Event-Listener, die du nicht mehr brauchst.
for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)); // 3 3 3
for (let j = 0; j < 3; j++) setTimeout(() => console.log(j)); // 0 1 2