Geschichte
In TypeScript wurden private Eigenschaften ursprünglich durch den Modifikator private eingeführt, während ab ECMAScript 2021 in JavaScript echte geschlossene Felder mithilfe des Symbols # unterstützt werden. Das Hauptziel besteht darin, Daten zu kapseln, um interne Details einer Klasse vor externem Zugriff zu schützen.
Problem
Der Modifikator private in TypeScript gewährleistet die Privatsphäre nur zur Kompilierungszeit, aber im kompilierten JavaScript sind diese Felder weiterhin über den direkten Zugriff auf Objekt-Eigenschaften verfügbar. Dies kann zu unbeabsichtigten Änderungen des Zustands des Objekts führen. ES Private Fields (#) sind auch zur Laufzeit von JS vollständig außerhalb der Klasse nicht zugänglich, was einen echten Datenschutz gewährleistet.
Lösung
TypeScript unterstützt beide Ansätze. Bei der Wahl zwischen ihnen orientieren Sie sich an dem gewünschten Schutzniveau und den Einschränkungen hinsichtlich der Kompatibilität mit JS-Versionen.
Beispielcode:
class Example { private hidden: number; #trulyHidden: string; constructor() { this.hidden = 42; this.#trulyHidden = 'secret'; } getHidden() { return this.hidden; } getTrulyHidden() { return this.#trulyHidden; } } const x = new Example(); // x.hidden — Fehler in TS, funktioniert aber über x['hidden'] in JS // x.#trulyHidden — Syntaxfehler selbst in JS
Wichtige Merkmale:
private garantiert die Privatsphäre nur zur Kompilierungszeit von TypeScript#field bietet echte Privatsphäre auf der Ebene der JavaScript-Ausführung# erfordert Unterstützung der modernen JS (ES2021+)Kann man auf ein privates Feld einer TypeScript-Klasse durch direkten Zugriff in JS zugreifen?
Ja, das ist möglich, da die Privatsphäre nur zur Kompilierungszeit realisiert wird. Im ursprünglichen JS-Feld wird es eine gewöhnliche Eigenschaft des Objekts sein. Zum Beispiel:
class A { private x = 1; } const a = new A(); console.log((a as any)["x"]); // 1
Kann man private Felder mit # in Schnittstellen verwenden oder sie mit type beschreiben?
Nein, #private Felder sind nur Teil der Implementierung der Klasse und können nicht in Schnittstellen, Typen beschrieben oder außerhalb der Klasse verwendet werden. Schnittstellen beschreiben nur öffentliche Mitglieder.
Kann man private Felder, die mit # deklariert wurden, erben?
Nein, solche Felder sind für abgeleitete Klassen überhaupt nicht zugänglich. Nur die Klasse selbst hat Zugriff darauf:
class Parent { #foo = 123; } class Child extends Parent { // this.#foo = 444; // Fehler }
private zum Schutz kritischer Daten — führt zu Schwachstellen bei direktem ZugriffIn einem Projekt zur Speicherung von Passwörtern wurde im User-Klasse das Feld private password verwendet. Ein Entwickler erhält zufällig Zugriff über user['password'] für Debugging-Zwecke, und das Feld wird von einem externen Modul geändert.
Vorteile:
Nachteile:
Der Entwickler verwendet das ES private field #password. Nun sind Zugriffsversuche auf das Feld über Indizierung oder in Ableitungen nicht möglich, der Datenschutz ist auch bei Verwendung von Drittanbieterbibliotheken und Werkzeugen gewährleistet.
Vorteile:
Nachteile: