Das Konzept der Getter und Setter ist in den heute gebräuchlichen Sprachen recht verbreitet. Wollten Sie schon einmal sicherstellen, dass eine bestimmte Aktion immer vor oder nach der Zuweisung eines Wertes zu einer Objekteigenschaft ausgeführt wird? Dies ist mit Settern möglich. Sie können auch jede Art von Verarbeitung durchführen, wenn Sie den Wert einer Eigenschaft abrufen, indem Sie Getter verwenden (z. B. Formatierung). Eine Möglichkeit, Getter und Setter zu implementieren, ist die Verwendung von Methoden, wie es in Java der Fall ist. Seit ES5 steht uns jedoch mit der get
– und set
-Syntax eine viel elegantere und praktischere Alternative zur Verfügung. Also, fangen wir an!
In JavaScript sind Objekte Sammlungen von Eigenschaften und Sie haben sie wahrscheinlich schon einmal zum Speichern von Daten verwendet. Eine Eigenschaft ist einfach ein Schlüssel-Werte-Paar. Hier ein Beispiel:
const options = {
timeout: 5000,
retries: 3,
ip: '192.168.1.20',
port: 4001,
};
Eigenschaften in einem Objekt können einfach gesetzt und gelesen werden, etwa so:
artist.name = 'Carice Anouk van Houten';console.log(artist.name); //=> "Carice Anouk van Houten"
Auch das ist definitiv nichts Neues, wenn Sie schon etwas Erfahrung mit JavaScript haben. Um einen Unterschied zwischen diesen regulären Eigenschaften und dem anderen Typ, den wir in diesem Artikel sehen werden, zu machen, können wir erstere als „Dateneigenschaften“ bezeichnen.
Getter und Setter: der alte Weg
Vor ES5 war die einzige Möglichkeit, Getter und Setter zu implementieren, die Verwendung regulärer Methoden. Wie im folgenden Beispiel:
Ich habe das Schlüsselwort function im obigen Beispiel beibehalten, um zu verdeutlichen, dass es hier keine Magie gibt. Nur normale Methoden. Wir hätten denselben Effekt auch mit der Methodendefinitionssyntax von ES2015 erzielen können, die kürzer und etwas eleganter ist:
const config = {
_port: 4001,
setPort(port) {
// ...
},
getPort() {
// ...
},
};
Die Verwendung dieser Arten von Gettern und Settern ist recht einfach:
config.setPort(8080);
console.log(config.getPort()); //=> 8080
Das Inkrementieren eines Wertes würde wie folgt ablaufen:
item.setQuantity(item.getQuantity() + 1);
Was im Vergleich zum direkten Inkrementieren einer Eigenschaft ziemlich langatmig aussieht:
item.quantity += 1;
// Or even simpler...
item.quantity++;
Getters und Setters: Warum?
In OO-Sprachen wie Java, C++ oder C# ist es möglich, die Mitglieder einer Klasse auf verschiedenen Ebenen mit Hilfe von Zugriffsmodifikatoren (wie public
, protected
und private
) freizugeben. Dies dient der Umsetzung eines wichtigen OOP-Konzepts, das als Data Hiding bezeichnet wird.
Eine sehr häufige Verwendung von Gettern und Settern in diesen Sprachen besteht darin, die Mitglieder einer Klasse auf sichere Weise offenzulegen. Zum Beispiel könnte man nur einen Getter implementieren, um sicherzustellen, dass ein privates Mitglied niemals von außerhalb der Klasse geändert wird. Ein Setter wiederum kann verwendet werden, um die übergebenen Werte zu validieren und die Integrität der Instanzen dieser Klasse zu bewahren.
Wie sieht es mit JavaScript aus?
In JavaScript liegen die Dinge ein wenig anders. Zum Zeitpunkt der Abfassung dieses Artikels gibt es in JS keine Zugriffsmodifikatoren. Die beste Möglichkeit, die wir derzeit haben, ist die Verwendung von Symbolen, die uns ein gewisses Maß an Privatsphäre bieten, wenn sie als Schlüssel verwendet werden. Manche Leute mögen sie allerdings nicht.
Ich halte das nicht für ein wirkliches Problem, da Sprachen, die Reflection haben, es Programmierern normalerweise erlauben, die Kapselung auf irgendeine Weise zu brechen. Das Problem, das ich bei Symbolen sehe, ist, dass sie nicht so praktisch zu verwenden sind, wie ein einfacher privater Accessor es wäre. Die gute Nachricht ist, dass ein EcmaScript-Vorschlag, der private Felder beinhaltet, bereits in Phase 3 ist. Und sie werden immun gegen jede Art von Reflexion sein.
Im Beispiel des vorherigen Abschnitts haben wir weder Symbole noch einen anderen Trick verwendet, um ein privates Mitglied zu simulieren. Die Eigenschaft _port
hat an sich nichts Besonderes. Sie ist einfach eine normale Dateneigenschaft und kann als solche direkt gesetzt oder gelesen werden, wobei die von uns erstellten Getter und Setter vollständig umgangen werden.
Da die Erläuterung von Symbolen und anderen Kapselungstechniken nicht der Zweck dieses Artikels ist, implementiere ich in seinen Codebeispielen keine privaten Eigenschaften. Denken Sie einfach daran, dass Getter und Setter häufig (aber nicht immer) verwendet werden, um den Zugriff auf gekapselte Mitglieder zu ermöglichen. Beachten Sie schließlich den Unterstrich vor dem Namen der Eigenschaft _port
. Es ist eine De-facto-Konvention unter JS-Entwicklern, die anzeigt, dass eine bestimmte Eigenschaft privat ist und nicht von außerhalb der Klasse, in der sie definiert ist, aufgerufen werden sollte.
Getters und Setters: der neue Weg mit Accessor-Eigenschaften
Accessor-Eigenschaften sind die moderne Art, Getter und Setter zu definieren. Was ihre Definition angeht, unterscheiden sie sich nicht so sehr von unserem vorherigen Beispiel, aber es ist ihre Verwendung, die wirklich anders ist. Passen wir zunächst unseren Code an, um Accessor-Eigenschaften zu verwenden:
Wie Sie sehen, haben sich in diesem Beispiel nur zwei Dinge geändert:
- Anstatt
setPort
undgetPort
Methoden zu haben. Wir verwenden die Syntaxset
undget
zusammen mit einem einzigen Namen für die Eigenschaft („port
„, in diesem Beispiel) - Wir brauchen das Schlüsselwort
function
hier nicht. Wenn Sie versuchen, es zu verwenden, erhalten Sie einen Syntaxfehler.
Wie verwendet man Accessor-Eigenschaften?
Die Definition einer Accessor-Eigenschaft ähnelt der Art und Weise, wie wir Getter und Setter der alten Schule erstellen, und ihre Verwendung unterscheidet sich nicht sichtbar von der Verwendung regulärer Dateneigenschaften:
config.port = 8080;
console.log(config.port); //=> 8080
Und so sieht ein Inkrement-Ausdruck aus:
timer.seconds += 1;
Ja. So einfach ist das. =)
Fazit
- Objekte sind Sammlungen von Eigenschaften
- Eine reguläre Eigenschaft ist nur ein Schlüssel-Wert-Paar und kann als „Dateneigenschaft“ bezeichnet werden
- Sie können Getter und Setter als normale Methoden implementieren. Das ist die „alte Schule“ in JavaScript.
- Getter und Setter werden normalerweise verwendet, um den Zugriff auf private Mitglieder einer Klasse zu ermöglichen.
- Accessor-Properties können sich genauso verhalten wie Getter und Setter auf Basis der alten regulären Methoden, aber ihre Verwendung ist so konzipiert, dass sie wie Daten-Properties aussehen.
Möchten Sie JavaScript beherrschen? Ich empfehle Ihnen die JavaScript-Kurse von Mosh.
Und wenn Ihnen dieser Artikel gefallen hat, dann teilen Sie ihn auch mit anderen!