So erweitern Sie die Antwort von @ loganfsmyth:
Die einzigen wirklich privaten Daten in JavaScript sind Variablen mit Gültigkeitsbereich. Sie können nicht über private Eigenschaften im Sinne von Eigenschaften verfügen, auf die intern wie auf öffentliche Eigenschaften zugegriffen wird. Sie können jedoch Gültigkeitsbereichsvariablen zum Speichern privater Daten verwenden.
Gültigkeitsbereichsvariablen
Der Ansatz hier besteht darin, den Umfang der Konstruktorfunktion, die privat ist, zum Speichern privater Daten zu verwenden. Damit Methoden auf diese privaten Daten zugreifen können, müssen sie auch im Konstruktor erstellt werden. Dies bedeutet, dass Sie sie mit jeder Instanz neu erstellen. Dies ist eine Leistungs- und Gedächtnisstrafe, aber einige glauben, dass die Strafe akzeptabel ist. Die Strafe kann für Methoden vermieden werden, die keinen Zugriff auf private Daten benötigen, indem diese wie gewohnt zum Prototyp hinzugefügt werden.
Beispiel:
function Person(name) {
let age = 20; // this is private
this.name = name; // this is public
this.greet = function () {
// here we can access both name and age
console.log(`name: ${this.name}, age: ${age}`);
};
}
let joe = new Person('Joe');
joe.greet();
// here we can access name but not age
Scoped WeakMap
Eine WeakMap kann verwendet werden, um die Leistung und den Speicherverlust des vorherigen Ansatzes zu vermeiden. WeakMaps ordnen Daten Objekten (hier Instanzen) so zu, dass nur mit dieser WeakMap auf sie zugegriffen werden kann. Daher verwenden wir die Methode mit Gültigkeitsbereichsvariablen, um eine private WeakMap zu erstellen, und verwenden diese WeakMap dann, um private Daten abzurufen, die mit verknüpft sindthis
. Dies ist schneller als die Methode mit Gültigkeitsbereichsvariablen, da alle Ihre Instanzen eine einzige WeakMap gemeinsam nutzen können. Sie müssen also keine Methoden neu erstellen, um sie auf ihre eigenen WeakMaps zugreifen zu lassen.
Beispiel:
let Person = (function () {
let privateProps = new WeakMap();
class Person {
constructor(name) {
this.name = name; // this is public
privateProps.set(this, {age: 20}); // this is private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${privateProps.get(this).age}`);
}
}
return Person;
})();
let joe = new Person('Joe');
joe.greet();
// here we can access joe's name but not age
In diesem Beispiel wird ein Objekt verwendet, um eine WeakMap für mehrere private Eigenschaften zu verwenden. Sie können auch mehrere WeakMaps verwenden und sie wie verwenden age.set(this, 20)
oder einen kleinen Wrapper schreiben und ihn auf andere Weise verwendenprivateProps.set(this, 'age', 0)
.
Die Privatsphäre dieses Ansatzes könnte theoretisch durch Manipulationen an der Welt verletzt werden WeakMap
Objekt . Das heißt, alle JavaScript kann durch verstümmelte Globals gebrochen werden. Unser Code basiert bereits auf der Annahme, dass dies nicht geschieht.
(Diese Methode könnte auch angewendet werden Map
, WeakMap
ist jedoch besser, da dadurch Map
Speicherlecks entstehen, wenn Sie nicht sehr vorsichtig sind. Zu diesem Zweck unterscheiden sich die beiden nicht voneinander.)
Halbe Antwort: Symbole mit Gültigkeitsbereich
Ein Symbol ist eine Art primitiver Wert, der als Eigenschaftsname dienen kann. Mit der Methode der Gültigkeitsbereichsvariablen können Sie ein privates Symbol erstellen und dann private Daten unter speichernthis[mySymbol]
.
Die Privatsphäre dieser Methode kann mit verletzt werden Object.getOwnPropertySymbols
, ist aber etwas umständlich zu tun.
Beispiel:
let Person = (function () {
let ageKey = Symbol();
class Person {
constructor(name) {
this.name = name; // this is public
this[ageKey] = 20; // this is intended to be private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${this[ageKey]}`);
}
}
return Person;
})();
let joe = new Person('Joe');
joe.greet();
// Here we can access joe's name and, with a little effort, age. ageKey is
// not in scope, but we can obtain it by listing all Symbol properties on
// joe with `Object.getOwnPropertySymbols(joe)`.
Halbe Antwort: Unterstriche
Verwenden Sie bei der alten Standardeinstellung einfach eine öffentliche Eigenschaft mit einem Unterstrichpräfix. Obwohl diese Konvention in keiner Weise ein Privateigentum ist, ist sie weit genug verbreitet, um zu kommunizieren, dass die Leser das Eigentum als privat behandeln sollten, was häufig die Arbeit erledigt. Als Gegenleistung für diesen Fehler erhalten wir einen Ansatz, der einfacher zu lesen, einfacher zu tippen und schneller ist.
Beispiel:
class Person {
constructor(name) {
this.name = name; // this is public
this._age = 20; // this is intended to be private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${this._age}`);
}
}
let joe = new Person('Joe');
joe.greet();
// Here we can access both joe's name and age. But we know we aren't
// supposed to access his age, which just might stop us.
Fazit
Ab ES2017 gibt es noch keine perfekte Möglichkeit, private Immobilien zu erwerben. Verschiedene Ansätze haben Vor- und Nachteile. Gültigkeitsbereichsvariablen sind wirklich privat. WeakMaps mit Gültigkeitsbereich sind sehr privat und praktischer als Variablen mit Gültigkeitsbereich. Symbole mit Gültigkeitsbereich sind einigermaßen privat und recht praktisch. Unterstriche sind oft privat genug und sehr praktisch.