Getter und Setter sind Funktionen oder Methoden zum Abrufen und Setzen der Werte von Variablen. Das Getter-Setter-Konzept ist in der Computerprogrammierung weit verbreitet: Fast alle höheren Programmiersprachen verfügen über eine Syntax zur Implementierung von Gettern und Settern, auch JavaScipt.
Lesen Sie auch: 4 nützliche JavaScript-Anweisungen, die Sie kennen sollten
In diesem Beitrag werden wir sehen, was Getters und Setters sind und wie man sie in JavaScript erstellt und verwendet.
- Getters und Setters und Kapselung
- Erstelle Getter und Setter
- 1. Mit Methoden
- 2. Mit Schlüsselwörtern
- Welcher Weg ist besser?
- Überschreibschutz
- Operationen innerhalb von Gettern und Settern
- Schützen Sie Daten mit Gettern und Settern
- Ungeschützte Daten
- 1. Blockscoping
- 2. Funktions-Scoping
- 3. Datenschutz ohne Scoping
- Wann sollten Sie Getter und Setter verwenden?
Getters und Setters und Kapselung
Die Idee der Getters und Setters wird immer in Verbindung mit Kapselung erwähnt. Verkapselung kann auf zwei Arten verstanden werden.
Erstens ist es die Einrichtung des Daten-Getter-Setter-Trios, um auf diese Daten zuzugreifen und sie zu verändern. Diese Definition ist nützlich, wenn einige Operationen, wie z.B. die Validierung, an den Daten durchgeführt werden müssen, bevor sie gespeichert oder angezeigt werden – Getter und Setter bieten dafür das perfekte Zuhause.
Zweitens gibt es eine strengere Definition, nach der die Kapselung durchgeführt wird, um die Daten zu verbergen, um sie für anderen Code unzugänglich zu machen, außer durch die Getter und Setter. Auf diese Weise überschreiben wir nicht versehentlich wichtige Daten mit einem anderen Code im Programm.
Erstelle Getter und Setter
1. Mit Methoden
Da Getter und Setter im Grunde Funktionen sind, die einen Wert holen/ändern, gibt es mehr als eine Möglichkeit, sie zu erstellen und zu verwenden. Der erste Weg ist:
var obj = { foo: 'this is the value of foo', getFoo: function() { return this.foo; }, setFoo: function(val) { this.foo = val; }}console.log(obj.getFoo());// "this is the value of foo"obj.setFoo('hello');console.log(obj.getFoo());// "hello"
Dies ist der einfachste Weg, Getter und Setter zu erstellen. Es gibt eine Eigenschaft foo
und es gibt zwei Methoden: getFoo
und setFoo
, um einen Wert für diese Eigenschaft zurückzugeben und zuzuweisen.
2. Mit Schlüsselwörtern
Eine „offiziellere“ und robustere Art, Getter und Setter zu erstellen, ist die Verwendung der Schlüsselwörter get
und set
.
Um einen Getter zu erstellen, setzen Sie das Schlüsselwort get
vor eine Funktionsdeklaration, die als Getter-Methode dienen soll, und verwenden Sie das Schlüsselwort set
auf die gleiche Weise, um einen Setter zu erstellen. Die Syntax lautet wie folgt:
var obj = { fooVal: 'this is the value of foo', get foo() { return this.fooVal; }, set foo(val) { this.fooVal = val; }}console.log(obj.foo);// "this is the value of foo"obj.foo = 'hello';console.log(obj.foo);// "hello"
Beachten Sie, dass die Daten nur unter einem Eigenschaftsnamen (fooVal
) gespeichert werden können, der sich von dem Namen der Getter-Setter-Methode (foo
) unterscheidet, da eine Eigenschaft, die den Getter-Setter enthält, nicht auch die Daten enthalten kann.
Welcher Weg ist besser?
Wenn Sie sich dafür entscheiden, Getter und Setter mit Schlüsselwörtern zu erstellen, können Sie den Zuweisungsoperator verwenden, um die Daten zu setzen, und den Punktoperator, um die Daten zu erhalten, auf dieselbe Weise, wie Sie auf den Wert einer regulären Eigenschaft zugreifen bzw. ihn setzen würden.
Wenn Sie sich jedoch für die erste Art der Kodierung von Gettern und Settern entscheiden, müssen Sie die Setter- und Getter-Methoden mit der Funktionsaufrufsyntax aufrufen, da es sich um typische Funktionen handelt (nichts Besonderes, wie die, die mit den Schlüsselwörtern get
und set
erstellt werden).
Außerdem besteht die Möglichkeit, dass Sie den Eigenschaften, die diese Getter- und Setter-Methoden enthielten, versehentlich einen anderen Wert zuweisen und sie dadurch vollständig verlieren! Etwas, worüber man sich bei der späteren Methode keine Sorgen machen muss.
Sie sehen also, warum ich sagte, dass die zweite Technik robuster ist.
Überschreibschutz
Wenn Sie aus irgendeinem Grund die erste Technik bevorzugen, machen Sie die Eigenschaften, die die Getter-Setter-Methoden enthalten, schreibgeschützt, indem Sie sie mit Object.defineProperties
erstellen. Eigenschaften, die über Object.defineProperties
, Object.defineProperty
und Reflect.defineProperty
erstellt werden, werden automatisch auf writable: false
konfiguriert, was „read-only“ bedeutet:
/* Overwrite prevention */var obj = { foo: 'this is the value of foo'};Object.defineProperties(obj, { 'getFoo': { value: function () { return this.foo; } }, 'setFoo': { value: function (val) { this.foo = val; } }});obj.getFoo = 66;// getFoo is not going to be overwritten!console.log(obj.getFoo());// "this is the value of foo"
Operationen innerhalb von Gettern und Settern
Wenn Sie die Getter und Setter eingeführt haben, können Sie fortfahren und Operationen mit den Daten durchführen, bevor Sie sie ändern oder zurückgeben.
Im folgenden Code werden die Daten in der Getter-Funktion mit einer Zeichenkette verkettet, bevor sie zurückgegeben werden, und in der Setter-Funktion wird vor der Aktualisierung geprüft, ob der Wert eine Zahl ist oder nicht.
var obj = { n: 67, get id() { return 'The ID is: ' + this.n; }, set id(val) { if (typeof val === 'number') this.n = val; }}console.log(obj.id);// "The ID is: 67"obj.id = 893;console.log(obj.id);// "The ID is: 893"obj.id = 'hello';console.log(obj.id);// "The ID is: 893"
Schützen Sie Daten mit Gettern und Settern
So weit haben wir die Verwendung von Gettern und Settern im ersten Kontext der Kapselung behandelt. Kommen wir nun zum zweiten, d.h. wie man Daten mit Hilfe von Gettern und Settern vor fremdem Code verstecken kann.
Ungeschützte Daten
Das Einrichten von Gettern und Settern bedeutet nicht, dass die Daten nur über diese Methoden zugänglich sind und verändert werden können. Im folgenden Beispiel werden die Daten direkt geändert, ohne die Getter- und Setter-Methoden zu berühren:
var obj = { fooVal: 'this is the value of foo', get foo() { return this.fooVal; }, set foo(val) { this.fooVal = val; }}obj.fooVal = 'hello';console.log(obj.foo);// "hello"
Wir haben den Setter nicht verwendet, sondern die Daten direkt geändert (fooVal
). Die Daten, die wir ursprünglich in obj
gesetzt haben, sind jetzt weg! Um zu verhindern, dass dies (versehentlich) passiert, müssen Sie Ihre Daten etwas schützen. Dies können Sie erreichen, indem Sie den Bereich, in dem Ihre Daten verfügbar sind, einschränken. Dies kann entweder durch Block-Scoping oder Funktions-Scoping geschehen.
1. Blockscoping
Eine Möglichkeit ist die Verwendung eines Blockbereichs, in dem die Daten mit dem Schlüsselwort let
definiert werden, das den Bereich auf diesen Block beschränkt.
Ein Blockbereich kann erstellt werden, indem Sie Ihren Code in ein Paar geschweifte Klammern setzen. Wenn du einen Blockbereich erstellst, stelle sicher, dass du einen Kommentar darüber schreibst, in dem du darum bittest, die geschweiften Klammern in Ruhe zu lassen, damit niemand die Klammern versehentlich entfernt, weil er denkt, dass es sich um zusätzliche überflüssige Klammern im Code handelt, oder dem Blockbereich ein Label hinzufügt.
/* BLOCK SCOPE, leave the braces alone! */{let fooVal = 'this is the value of foo';var obj = { get foo() { return fooVal; }, set foo(val) { fooVal = val } }}fooVal = 'hello';// not going to affect the fooVal inside the blockconsole.log(obj.foo);// "this is the value of foo"
Das Ändern/Erstellen von fooVal
außerhalb des Blocks wird sich nicht auf die fooVal
auswirken, die innerhalb der Getters Setters referenziert werden.
2. Funktions-Scoping
Die häufigste Art, die Daten mit Scoping zu schützen, besteht darin, die Daten innerhalb einer Funktion zu halten und ein Objekt mit den Gettern und Settern aus dieser Funktion zurückzugeben.
function myobj(){ var fooVal = 'this is the value of foo'; return { get foo() { return fooVal; }, set foo(val) { fooVal = val } }}fooVal = 'hello';// not going to affect our original fooValvar obj = myobj();console.log(obj.foo);// "this is the value of foo"
Das von der myobj()
-Funktion zurückgegebene Objekt (mit dem foo()
Getter und Setter darin) wird in obj
gespeichert, und dann wird obj
verwendet, um den Getter und Setter aufzurufen.
3. Datenschutz ohne Scoping
Es gibt noch eine andere Möglichkeit, wie Sie Ihre Daten vor dem Überschreiben schützen können, ohne ihren Geltungsbereich zu begrenzen. Die Logik dahinter ist folgende: wie kann man ein Stück Daten ändern, wenn man nicht weiß, wie es heißt?
Wenn die Daten einen nicht so leicht reproduzierbaren Variablen-/Eigenschaftsnamen haben, ist die Wahrscheinlichkeit groß, dass niemand (nicht einmal wir selbst) sie überschreiben wird, indem wir dieser Variable/dem Eigenschaftsnamen einen Wert zuweisen.
var obj = { s89274934764: 'this is the value of foo', get foo() { return this.s89274934764; }, set foo(val) { this.s89274934764 = val; }}console.log(obj.foo);// "this is the value of foo"
Siehst du, das ist eine Möglichkeit, die Dinge zu regeln. Obwohl der von mir gewählte Name nicht wirklich gut ist, können Sie auch zufällige Werte oder Symbole verwenden, um Eigenschaftsnamen zu erstellen, wie es von Derick Bailey in diesem Blogbeitrag vorgeschlagen wird. Das Hauptziel ist es, die Daten vor anderem Code verborgen zu halten und einem Getter-Setter-Paar den Zugriff/Aktualisierung zu ermöglichen.
Wann sollten Sie Getter und Setter verwenden?
Jetzt kommt die große Frage: Fangen Sie jetzt an, allen Ihren Daten Getter und Setter zuzuweisen?
Wenn Sie Daten verstecken, haben Sie keine andere Wahl.
Aber wenn Ihre Daten für anderen Code sichtbar sind, müssen Sie dann immer noch Getters und Setters verwenden, nur um sie mit Code zu bündeln, der einige Operationen mit ihnen ausführt? Ich würde sagen, ja. Der Code summiert sich sehr schnell. Das Erstellen von Mikroeinheiten einzelner Daten mit eigenem Getter-Setter verschafft Ihnen eine gewisse Unabhängigkeit bei der Arbeit an diesen Daten, ohne andere Teile des Codes zu beeinträchtigen.
Lesen Sie auch: 10 Gründe, warum Sie Code-Optimierung brauchen