Klassen in JavaScript
Im letzten Artikel haben wir einige grundlegende Konzepte der objektorientierten Programmierung (OOP) eingeführt und ein Beispiel besprochen, in dem wir OOP-Prinzipien genutzt haben, um Professoren und Studenten in einer Schule zu modellieren.
Wir haben auch darüber gesprochen, wie es möglich ist, Prototypen und Konstruktoren zu verwenden, um ein solches Modell zu implementieren, und dass JavaScript auch Funktionen bietet, die eher den klassischen OOP-Konzepten entsprechen.
In diesem Artikel werden wir diese Funktionen durchgehen. Es ist wichtig zu bedenken, dass die hier beschriebenen Funktionen keine neue Methode zur Kombination von Objekten darstellen: im Hintergrund verwenden sie immer noch Prototypen. Sie sind lediglich eine Möglichkeit, das Einrichten einer Prototyp-Kette zu erleichtern.
Voraussetzungen: | Vertrautheit mit den Grundlagen von JavaScript (insbesondere Objektgrundlagen) und objektorientierten JavaScript-Konzepten, die in den vorherigen Lektionen in diesem Modul behandelt wurden. |
---|---|
Lernziele: |
|
Klassen und Konstruktoren
Sie können eine Klasse mit dem Schlüsselwort class
deklarieren. Hier ist eine Klassendeklaration für unsere Person
aus dem vorherigen Artikel:
class Person {
name;
constructor(name) {
this.name = name;
}
introduceSelf() {
console.log(`Hi! I'm ${this.name}`);
}
}
Dies deklariert eine Klasse namens Person
, mit:
- einer
name
-Eigenschaft. - einem Konstruktor, der einen
name
-Parameter akzeptiert, der verwendet wird, um diename
-Eigenschaft des neuen Objekts zu initialisieren. - einer
introduceSelf()
-Methode, die auf die Eigenschaften des Objekts mitthis
verweisen kann.
Die Erklärung name;
ist optional: Sie können sie weglassen, und die Zeile this.name = name;
im Konstruktor wird die name
-Eigenschaft erstellen, bevor sie initialisiert wird. Das explizite Auflisten von Eigenschaften in der Klassendeklaration kann es jedoch einfacher machen, die Eigenschaften zu erkennen, die Teil dieser Klasse sind.
Sie könnten die Eigenschaft auch mit einem Standardwert initialisieren, wenn Sie sie deklarieren, mit einer Zeile wie name = '';
.
Der Konstruktor wird mit dem Schlüsselwort constructor
definiert. Genau wie ein Konstruktor außerhalb einer Klassendefinition wird er:
- ein neues Objekt erstellen
this
an das neue Objekt binden, sodass Sie im Konstruktorcode aufthis
verweisen können- den Code im Konstruktor ausführen
- das neue Objekt zurückgeben.
Angesichts des obigen Klassendeklarationscodes können Sie eine neue Person
-Instanz wie folgt erstellen und verwenden:
const giles = new Person("Giles");
giles.introduceSelf(); // Hi! I'm Giles
Beachten Sie, dass wir den Konstruktor mit dem Namen der Klasse aufrufen, in diesem Beispiel Person
.
Konstruktoren weglassen
Wenn Sie keine spezielle Initialisierung benötigen, können Sie den Konstruktor weglassen, und es wird ein Standardkonstruktor für Sie generiert:
class Animal {
sleep() {
console.log("zzzzzzz");
}
}
const spot = new Animal();
spot.sleep(); // 'zzzzzzz'
Vererbung
Angesichts unserer oben beschriebenen Person
-Klasse, lassen Sie uns die Professor
-Unterklasse definieren.
class Professor extends Person {
teaches;
constructor(name, teaches) {
super(name);
this.teaches = teaches;
}
introduceSelf() {
console.log(
`My name is ${this.name}, and I will be your ${this.teaches} professor.`,
);
}
grade(paper) {
const grade = Math.floor(Math.random() * (5 - 1) + 1);
console.log(grade);
}
}
Wir verwenden das Schlüsselwort extends
, um auszudrücken, dass diese Klasse von einer anderen Klasse erbt.
Die Professor
-Klasse fügt eine neue Eigenschaft teaches
hinzu, daher deklarieren wir diese.
Da wir teaches
setzen möchten, wenn ein neuer Professor
erstellt wird, definieren wir einen Konstruktor, der name
und teaches
als Argumente nimmt. Das erste, was dieser Konstruktor tut, ist den Konstruktor der Superklasse mit super()
aufzurufen und den name
-Parameter weiterzugeben. Der Konstruktor der Superklasse kümmert sich um das Setzen von name
. Danach setzt der Professor
-Konstruktor die teaches
-Eigenschaft.
Hinweis:
Wenn eine Unterklasse ihre eigene Initialisierung durchzuführen hat, muss sie zuerst den Konstruktor der Superklasse mit super()
aufrufen und dabei alle Parameter übergeben, die der Konstruktor der Superklasse erwartet.
Wir haben auch die Methode introduceSelf()
der Superklasse überschrieben und eine neue Methode grade()
hinzugefügt, um eine Arbeit zu benoten (unser Professor ist nicht sehr gut und weist den Arbeiten zufällige Noten zu).
Mit dieser Deklaration können wir jetzt Professoren erstellen und verwenden:
const walsh = new Professor("Walsh", "Psychology");
walsh.introduceSelf(); // 'My name is Walsh, and I will be your Psychology professor'
walsh.grade("my paper"); // some random grade
Kapselung
Schließlich wollen wir sehen, wie man Kapselung in JavaScript implementiert. Im letzten Artikel haben wir diskutiert, wie wir die Eigenschaft year
von Student
privat machen möchten, damit wir die Regeln für Bogenschießenklassen ändern können, ohne den Code zu brechen, der die Student
-Klasse verwendet.
Hier ist eine Deklaration der Student
-Klasse, die genau das tut:
class Student extends Person {
#year;
constructor(name, year) {
super(name);
this.#year = year;
}
introduceSelf() {
console.log(`Hi! I'm ${this.name}, and I'm in year ${this.#year}.`);
}
canStudyArchery() {
return this.#year > 1;
}
}
In dieser Klassendeklaration ist #year
ein privates Feld. Wir können ein Student
-Objekt konstruieren, und es kann #year
intern verwenden, aber wenn Code außerhalb des Objekts versucht, auf #year
zuzugreifen, löst der Browser einen Fehler aus:
const summers = new Student("Summers", 2);
summers.introduceSelf(); // Hi! I'm Summers, and I'm in year 2.
summers.canStudyArchery(); // true
summers.#year; // SyntaxError
Hinweis: Code, der in der Chrome-Konsole ausgeführt wird, kann auf private Elemente außerhalb der Klasse zugreifen. Dies ist eine Lockerung der JavaScript-Syntaxbeschränkung, die nur in den DevTools gilt.
Private Felder müssen in der Klassendeklaration angegeben werden und ihre Namen beginnen mit #
.
Private Methoden
Sie können sowohl private Methoden als auch private Felder haben. Genau wie private Felder beginnen die Namen privater Methoden mit #
, und sie können nur von den eigenen Methoden des Objekts aufgerufen werden:
class Example {
somePublicMethod() {
this.#somePrivateMethod();
}
#somePrivateMethod() {
console.log("You called me?");
}
}
const myExample = new Example();
myExample.somePublicMethod(); // 'You called me?'
myExample.#somePrivateMethod(); // SyntaxError
Testen Sie Ihre Fähigkeiten!
Sie haben das Ende dieses Artikels erreicht, aber können Sie sich an die wichtigsten Informationen erinnern? Sie können einige weitere Tests finden, um zu überprüfen, ob Sie diese Informationen behalten haben, bevor Sie fortfahren — siehe Testen Sie Ihre Fähigkeiten: Objektorientiertes JavaScript.
Zusammenfassung
In diesem Artikel haben wir die wichtigsten Werkzeuge durchgearbeitet, die in JavaScript zur Verfügung stehen, um objektorientierte Programme zu schreiben. Wir haben hier nicht alles abgedeckt, aber das sollte ausreichen, um Ihnen einen Start zu ermöglichen. Unser Artikel über Klassen ist ein guter Ort, um mehr zu erfahren.