Private und geschützte Klassenmitglieder in JavaScript
Erfahren Sie, wie JavaScript mit dem #-Präfix echte Privatsphäre und mit der _-Konvention geschützte Mitglieder umsetzt – inklusive Getter, Setter und Best Practices.
Eine Klasse muss häufig Teile ihrer internen Implementierung verbergen, damit externer Code diese nicht direkt lesen oder verändern kann. Diese Seite erklärt die beiden Ansätze, die JavaScript dafür bietet: wirklich private Mitglieder, die mit einem #-Präfix deklariert werden, und die _-Unterstrich-Konvention, mit der Entwickler Mitglieder als „geschützt" markieren (d. h. nur für die Klasse und ihre Unterklassen bestimmt).
Sie erfahren, wann Sie welchen Ansatz verwenden sollten, warum #-Felder von außen wirklich nicht zugänglich sind und wie Sie private Felder mit Gettern und Settern kombinieren können, um eine kontrollierte, validierte Schnittstelle bereitzustellen. Wenn Klassen für Sie neu sind, lesen Sie zunächst das Kapitel zur grundlegenden Klassensyntax.
Einführung in die Kapselung in JavaScript
Kapselung ist ein grundlegendes Prinzip der objektorientierten Programmierung (OOP): Sie bündelt Daten (Variablen) und die Methoden (Funktionen), die auf diesen Daten operieren, in einer einzigen Einheit – einem object – und kontrolliert den Zugriff auf die Interna dieses object. Das Ziel besteht darin, eine kleine, bewusst gestaltete öffentliche Schnittstelle bereitzustellen und die Implementierungsdetails dahinter zu verbergen.
Warum ist das wichtig? Wenn interner Zustand verborgen ist, kann externer Code Ihr object nicht in einen ungültigen Zustand versetzen, und Sie können die interne Funktionsweise der Klasse ändern, ohne den Code zu beeinträchtigen, der sie nutzt. In JavaScript wird Kapselung mit privaten #-Feldern und -Methoden erreicht. JavaScript besitzt keinen nativen protected-Modifikator, daher simulieren Entwickler ihn mit einer Namenskonvention (dem _-Präfix), wie unten erläutert.
Private Eigenschaften und Methoden
Ein privates Klassenmitglied wird mit einem #-Präfix im Namen deklariert. Es kann nur innerhalb des Klassenrumpfs aufgerufen werden – jeder Versuch, es von außen zu lesen oder zu schreiben, führt zu einem harten Syntaxfehler, nicht nur zu undefined. Dies ist eine echte, sprachlich erzwungene Privatsphäre.
Ein Feld muss im Klassenrumpf deklariert werden, bevor es verwendet werden kann (Sie können ein #-Feld nicht spontan im Konstruktor anlegen, wie es bei einer öffentlichen Eigenschaft möglich wäre). Beachten Sie außerdem, dass private #-Felder nicht aufzählbar sind: Sie erscheinen nicht in Object.keys(), for...in oder der Ausgabe von JSON.stringify().
Warum # wirklich privat ist
Anders als die Unterstrich-Konvention ist ein #-Feld außerhalb der Klasse unsichtbar. Sie können nicht über user.#name, über einen Klammerzugriff wie user[\"#name\"] oder über Object.keys() darauf zugreifen. Die erste Form ist ein Syntaxfehler; die anderen finden das Feld schlicht nicht.
Private Methoden
Auch Methoden können privat sein: Stellen Sie dem Methodennamen # voran. Eine private Methode eignet sich für interne Hilfsfunktionen, die Aufrufer niemals direkt aufrufen sollen – zum Beispiel Validierungs- oder Formatierungslogik, die die öffentliche API unterstützt, aber nicht Teil davon ist.
Geschützte Eigenschaften und Methoden (die _-Konvention)
JavaScript besitzt kein protected-Schlüsselwort. Gemäß der Konvention wird ein Mitglied, das von der Klasse und ihren Unterklassen verwendet werden soll – nicht aber von externem Code –, mit einem einzelnen Unterstrich _ vorangestellt. Dies ist rein ein Signal an andere Entwickler; ein _-Mitglied bleibt von überall aus vollständig les- und schreibbar. Verwenden Sie es, wenn Unterklassen Zugriff benötigen (ein #-Feld ist in Unterklassen nicht zugänglich), und akzeptieren Sie, dass der Schutz auf Vereinbarung beruht, nicht auf Durchsetzung.
Da _-Mitglieder wie normale Eigenschaften vererbt werden, kann eine Unterklasse auf sie zurückgreifen. Dies ist der praktische Grund, die Konvention anstelle von # zu verwenden, wenn ein Design für Vererbung vorgesehen ist:
Accessor-basierte Kapselung: Best Practices
Beachten Sie beim Einsatz privater und geschützter Eigenschaften und Methoden in Ihren JavaScript-Projekten die folgenden Best Practices, um deren Vorteile optimal zu nutzen:
- Verwenden Sie private Felder für sensible oder unveränderliche Daten: Speichern Sie alles, was nicht direkt berührt werden soll – interne Zähler, gecachte Werte, Rohzustand – als
#-Feld. Das garantiert Integrität und verhindert unbeabsichtigte Nebeneffekte. - Nutzen Sie Getter und Setter: Halten Sie das Feld privat und stellen Sie es über einen Getter und Setter bereit. Der Setter bietet die Möglichkeit, Eingaben zu validieren oder zu transformieren, bevor sie das private Feld erreichen, sodass das object niemals einen ungültigen Wert halten kann.
Im folgenden Beispiel kann #age nur über den Setter verändert werden, der negative Zahlen ablehnt:
Sie können auch schreibgeschützten Zustand bereitstellen, indem Sie einen Getter ohne passenden Setter definieren – der Verwender kann den Wert lesen, hat aber keine Möglichkeit, das zugrunde liegende private Feld zu überschreiben.
- Verwenden Sie geschützte Mitglieder für Vererbung: Setzen Sie geschützte Eigenschaften und Methoden ein, wenn diese innerhalb von Unterklassen zugänglich sein sollen. Diese Strategie ermöglicht eine flexiblere und hierarchischere Struktur in Ihren Anwendungen.
Fortgeschrittene Techniken und Muster
Über die Grundlagen hinaus erlaubt JavaScript anspruchsvollere Muster und Techniken, um Ihren Code effektiv zu kapseln und zu strukturieren:
- Module-Muster: Nutzen Sie Closures und sofort aufgerufene Funktionsausdrücke (IIFE), um private Geltungsbereiche zu erzeugen.
- Factory-Funktionen: Diese Funktionen geben neue objects zurück und ermöglichen private Daten durch Closures, ohne das
new-Schlüsselwort zu benötigen. - Proxies: JavaScript-Proxies können verwendet werden, um schützende Hüllen um objects zu erstellen und den Zugriff auf deren Eigenschaften und Methoden zu kontrollieren.
Fazit
Verwenden Sie #-Felder und -Methoden, wenn Sie echte, erzwungene Privatsphäre wünschen, auf die kein externer Code zugreifen kann. Verwenden Sie die _-Unterstrich-Konvention, wenn Unterklassen Zugriff benötigen und der Schutz auf Vereinbarung beruhen kann. Kombinieren Sie private Felder mit Gettern und Settern, um eine kontrollierte, validierte Schnittstelle bereitzustellen – und reine Getter (ohne Setter) dort, wo Zustand beobachtbar, aber nicht veränderbar sein soll.
Verwandte Themen
- Grundlegende Klassensyntax — Klassen, Konstruktoren und Methoden deklarieren.
- Getter und Setter für Eigenschaften — das Accessor-Muster, das auf dieser Seite durchgängig verwendet wird.
- Statische Eigenschaften und Methoden — Mitglieder, die zur Klasse selbst gehören, einschließlich privater statischer Felder.