Signatur
Beschreibung
using ist eine neue Deklarationsform ähnlich const, die Ressourcen-Management direkt in die Sprache integriert. Wird der Block verlassen – egal ob normal, per return, break, throw oder continue –, ruft die JavaScript-Runtime automatisch die Methode [Symbol.dispose]() des gebundenen Objekts auf. Das schließt Dateien, Datenbankverbindungen, Locks, Streams und andere Ressourcen zuverlässig, ohne dass ein try/finally-Block von Hand geschrieben werden muss.
Eine mit using deklarierte Variable verhält sich in Bezug auf Sichtbarkeit wie const: Sie ist block-skopiert, nicht hoisted (Temporal Dead Zone gilt), und darf nach der Deklaration nicht neu zugewiesen werden. Der Wert muss entweder null, undefined oder ein Objekt mit einer [Symbol.dispose]-Methode sein – andernfalls wird ein TypeError geworfen. Bei null oder undefined wird dispose stillschweigend übersprungen.
Mehrere using-Deklarationen im selben Block werden in umgekehrter Reihenfolge ihrer Deklaration freigegeben (LIFO – Last In, First Out), analog zu einem Stack von finally-Blöcken. Wirft eine dispose-Methode selbst eine Exception, wird diese mit eventuellen früheren Fehlern zu einem SuppressedError zusammengefasst, sodass keine Fehlerinformation verloren geht.
Für asynchrone Ressourcen (z. B. Datenbankverbindungen mit asynchronem Schließen) existiert die Gegenstück-Deklaration await using, die [Symbol.asyncDispose] aufruft und daher in async-Funktionen verwendet werden muss.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $identifier Pflicht | string | — | Name der zu deklarierenden Variable. Bindungsregeln wie bei const: block-skopiert, keine Neuzuweisung. |
| $expression Pflicht | object | null | undefined | — | Ausdruck, der ausgewertet wird. Muss null, undefined oder ein Objekt mit einer [Symbol.dispose]-Methode sein. Jeder andere Wert wirft sofort einen TypeError. |
Rückgabewert
Beispiele
Eigene Ressource mit Symbol.dispose
class DatabaseConnection {
#name;
constructor(name) {
this.#name = name;
console.log(`[${this.#name}] Verbindung geöffnet`);
}
query(sql) {
console.log(`[${this.#name}] Abfrage: ${sql}`);
return [{ id: 1 }];
}
[Symbol.dispose]() {
console.log(`[${this.#name}] Verbindung geschlossen`);
}
}
function fetchUsers() {
using db = new DatabaseConnection('primary');
const users = db.query('SELECT * FROM users');
console.log('Gefunden:', users.length, 'Nutzer');
// db[Symbol.dispose]() wird hier automatisch aufgerufen
}
fetchUsers();
LIFO-Reihenfolge bei mehreren using-Deklarationen
const makeResource = (name) => ({
[Symbol.dispose]() {
console.log(`Freigabe: ${name}`);
}
});
{
using a = makeResource('A');
using b = makeResource('B');
using c = makeResource('C');
console.log('Block wird verlassen…');
}
// Freigabe in umgekehrter Reihenfolge (LIFO)
Fehler-Handling mit SuppressedError
const faultyResource = {
[Symbol.dispose]() {
throw new Error('Fehler beim Schließen');
}
};
try {
using res = faultyResource;
throw new Error('Fehler im Block');
} catch (err) {
// err ist ein SuppressedError
console.log(err instanceof SuppressedError); // true
console.log('Primärer Fehler:', err.error.message);
console.log('Unterdrückter Fehler:', err.suppressed.message);
}
Verwendung mit DisposableStack
// DisposableStack bündelt mehrere Ressourcen in einem Stack
const openFile = (path) => ({ path, [Symbol.dispose]() { console.log(`Datei geschlossen: ${this.path}`); } });
const acquireLock = (id) => ({ id, [Symbol.dispose]() { console.log(`Lock freigegeben: ${this.id}`); } });
function processFile(path) {
using stack = new DisposableStack();
const file = stack.use(openFile(path));
const lock = stack.use(acquireLock('file-lock-42'));
console.log(`Verarbeite: ${file.path} mit Lock ${lock.id}`);
// Beim Verlassen der Funktion: Lock zuerst, dann Datei
}
processFile('/data/report.csv');
// Wichtig · Fallstricke
Browser- und Laufzeit-Unterstützung: using ist Teil des TC39-Proposals „Explicit Resource Management" (Stage 3 → Stage 4 in ES2026). Natives Support besteht ab Chrome/V8 134+, Node.js 22+ (mit Flag --harmony-explicit-resource-management ab v20) sowie Deno 1.40+. Firefox und Safari unterstützen es noch nicht nativ (Stand: Mitte 2025). TypeScript transpiliert using ab Version 5.2.
- Kein
var-Äquivalent:usingist immer block-skopiert; ein function-skopiertes Pendant existiert nicht. - Kein Destructuring:
using { a, b } = …ist nicht erlaubt. Die Deklaration bindet immer genau eine Variable. null/undefinedsind erlaubt –disposewird dann stillschweigend übersprungen. Alle anderen primitiven Werte (number,string, …) werfen einenTypeError.- Reihenfolge der Bereinigung: Mehrere
using-Deklarationen werden in LIFO-Reihenfolge aufgelöst, genau wie verschachteltefinally-Blöcke. - Asynchrone Variante: Für Ressourcen, die asynchrones Schließen benötigen (
[Symbol.asyncDispose]), mussawait usinginnerhalb einerasync-Funktion verwendet werden. SuppressedError: Wirft sowohl der Block als auch eindispose-Aufruf, werden beide Fehler in einemSuppressedErrorgebündelt (error= neuerer Fehler,suppressed= älterer).