JavaScript Closures und Scope verstehen | Enjyn Gruppe
Hallo Welt
Hallo Welt
Original Lingva Deutsch
Übersetzung wird vorbereitet...
Dieser Vorgang kann bis zu 60 Sekunden dauern.
Diese Seite wird erstmalig übersetzt und dann für alle Besucher gespeichert.
0%
DE Zurück zu Deutsch
Übersetzung durch Lingva Translate

235 Dokumentationen verfügbar

Wissensdatenbank

JavaScript Closures Scope

Zuletzt aktualisiert: 20.01.2026 um 11:26 Uhr

JavaScript Closures und Scope verstehen

Closures sind eines der mächtigsten Konzepte in JavaScript. Lernen Sie Scope-Regeln und praktische Closure-Patterns.

Scope-Arten in JavaScript

Scope Beschreibung Deklaration
Global Überall verfügbar Außerhalb von Funktionen
Function Nur in der Funktion var, function
Block Nur im Block {} let, const
Module Nur im Modul ES6 Modules

Lexical Scope

// JavaScript verwendet LEXICAL SCOPE (auch: Static Scope)
// Der Scope wird zur SCHREIBZEIT festgelegt, nicht zur Laufzeit

const global = 'Ich bin global';

function outer() {
    const outerVar = 'Ich bin in outer';

    function inner() {
        const innerVar = 'Ich bin in inner';

        // inner kann auf alles zugreifen:
        console.log(innerVar);   // ✅ eigener Scope
        console.log(outerVar);   // ✅ äußerer Scope (Closure!)
        console.log(global);     // ✅ globaler Scope
    }

    inner();
    // console.log(innerVar);  // ❌ ReferenceError
}

outer();
// console.log(outerVar);      // ❌ ReferenceError

Was ist eine Closure?

// Eine Closure entsteht, wenn eine Funktion auf Variablen
// aus ihrem äußeren Scope zugreift - auch nachdem die
// äußere Funktion bereits beendet ist!

function createCounter() {
    let count = 0;  // Diese Variable wird "eingeschlossen"

    return function() {
        count++;    // Zugriff auf count aus äußerem Scope
        return count;
    };
}

const counter = createCounter();
// createCounter() ist BEENDET, aber count lebt weiter!

console.log(counter());  // 1
console.log(counter());  // 2
console.log(counter());  // 3

// count ist von außen nicht zugänglich!
// console.log(count);  // ❌ ReferenceError

Closure für private Variablen

function createBankAccount(initialBalance) {
    let balance = initialBalance;  // Private Variable
    const transactions = [];       // Private Array

    return {
        deposit(amount) {
            if (amount > 0) {
                balance += amount;
                transactions.push({ type: 'deposit', amount });
                return balance;
            }
        },

        withdraw(amount) {
            if (amount > 0 && amount <= balance) {
                balance -= amount;
                transactions.push({ type: 'withdraw', amount });
                return balance;
            }
            return 'Nicht genug Guthaben';
        },

        getBalance() {
            return balance;  // Nur lesen, nicht direkt ändern
        },

        getTransactions() {
            return [...transactions];  // Kopie zurückgeben
        }
    };
}

const account = createBankAccount(100);
account.deposit(50);      // 150
account.withdraw(30);     // 120
account.getBalance();     // 120

// Direkt auf balance zugreifen? UNMÖGLICH!
// account.balance = 1000000;  // Erstellt nur neue Property
// account.getBalance();       // Immer noch 120

Das klassische Loop-Problem

// ❌ PROBLEM mit var
for (var i = 0; i < 3; i++) {
    setTimeout(() => {
        console.log(i);  // Gibt 3, 3, 3 aus!
    }, 100);
}
// var ist function-scoped, nicht block-scoped
// Alle Callbacks referenzieren dasselbe i

// ✅ LÖSUNG 1: let verwenden
for (let i = 0; i < 3; i++) {
    setTimeout(() => {
        console.log(i);  // Gibt 0, 1, 2 aus!
    }, 100);
}
// let ist block-scoped, jede Iteration hat eigenes i

// ✅ LÖSUNG 2: IIFE (Immediately Invoked Function Expression)
for (var i = 0; i < 3; i++) {
    (function(j) {
        setTimeout(() => {
            console.log(j);  // Gibt 0, 1, 2 aus!
        }, 100);
    })(i);  // i wird als j "eingefangen"
}

Praktische Closure-Patterns

// 1. MEMOIZATION - Ergebnisse cachen
function memoize(fn) {
    const cache = {};  // Closure über cache

    return function(...args) {
        const key = JSON.stringify(args);

        if (key in cache) {
            console.log('Aus Cache:', key);
            return cache[key];
        }

        const result = fn.apply(this, args);
        cache[key] = result;
        return result;
    };
}

const expensiveCalc = memoize((n) => {
    console.log('Berechne...');
    return n * n;
});

expensiveCalc(5);  // "Berechne..." → 25
expensiveCalc(5);  // "Aus Cache:" → 25 (keine Berechnung)
// 2. FUNCTION FACTORY
function createMultiplier(factor) {
    return function(number) {
        return number * factor;
    };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

double(5);  // 10
triple(5);  // 15
// 3. ONCE - Funktion nur einmal ausführen
function once(fn) {
    let called = false;
    let result;

    return function(...args) {
        if (!called) {
            called = true;
            result = fn.apply(this, args);
        }
        return result;
    };
}

const initialize = once(() => {
    console.log('Initialisierung...');
    return 'Fertig';
});

initialize();  // "Initialisierung..." → "Fertig"
initialize();  // → "Fertig" (keine erneute Ausführung)
// 4. DEBOUNCE - Verzögerte Ausführung
function debounce(fn, delay) {
    let timeoutId;

    return function(...args) {
        clearTimeout(timeoutId);

        timeoutId = setTimeout(() => {
            fn.apply(this, args);
        }, delay);
    };
}

const searchInput = debounce((query) => {
    console.log('Suche nach:', query);
    // API Call...
}, 300);

// Wird nur einmal ausgeführt (nach 300ms Pause)
searchInput('H');
searchInput('He');
searchInput('Hel');
searchInput('Hell');
searchInput('Hello');  // Nur dieser wird ausgeführt

Closure-Fallen vermeiden

// ❌ Memory Leak durch Closure
function createHandler() {
    const hugeData = new Array(1000000).fill('x');

    return function handler() {
        // hugeData wird nie freigegeben!
        console.log('Handler aufgerufen');
    };
}

// ✅ Besser: Nur benötigte Daten einschließen
function createHandler() {
    const hugeData = new Array(1000000).fill('x');
    const neededValue = hugeData.length;  // Nur das Nötige

    return function handler() {
        console.log('Länge:', neededValue);
    };
}
// ❌ Unbeabsichtigte Closure
function setupButtons() {
    for (var i = 0; i < buttons.length; i++) {
        buttons[i].onclick = function() {
            console.log('Button', i);  // Immer letzter Index!
        };
    }
}

// ✅ Richtig mit let oder bind
function setupButtons() {
    for (let i = 0; i < buttons.length; i++) {
        buttons[i].onclick = function() {
            console.log('Button', i);  // Korrekter Index
        };
    }
}
💡 Merke: Eine Closure ist eine Funktion plus ihre lexikalische Umgebung. Sie ermöglicht private Variablen, State-Management und viele nützliche Patterns. Achten Sie auf Memory Leaks bei großen eingeschlossenen Objekten!

Weitere Informationen

Enjix Beta

Enjyn AI Agent

Hallo 👋 Ich bin Enjix — wie kann ich dir helfen?
120