Чтобы расширить ответ @ loganfsmyth:
Единственные действительно личные данные в JavaScript - это переменные в области видимости. Вы не можете иметь частные свойства в том смысле, что к свойствам обращаются изнутри так же, как к публичным свойствам, но вы можете использовать переменные области действия для хранения личных данных.
Переменные области
Подход здесь состоит в том, чтобы использовать область функции конструктора, которая является частной, для хранения личных данных. Чтобы методы имели доступ к этим частным данным, они также должны быть созданы внутри конструктора, а это означает, что вы воссоздаете их с каждым экземпляром. Это снижение производительности и памяти, но некоторые считают, что это приемлемое ограничение. Наказания можно избежать для методов, которым не нужен доступ к частным данным, добавив их в прототип, как обычно.
Пример:
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
Scaped WeakMap
WeakMap может использоваться, чтобы избежать производительности предыдущего подхода и потери памяти. WeakMaps связывают данные с объектами (здесь, экземплярами) таким образом, что к ним можно получить доступ только с помощью этого WeakMap. Итак, мы используем метод переменных области видимости для создания приватного WeakMap, а затем используем этот WeakMap для извлечения приватных данных, связанных с this. Это быстрее, чем метод переменных области видимости, потому что все ваши экземпляры могут совместно использовать один WeakMap, поэтому вам не нужно пересоздавать методы просто для того, чтобы они получили доступ к своим собственным WeakMaps.
Пример:
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
В этом примере объект используется для использования одного WeakMap для нескольких частных свойств; Вы также можете использовать несколько WeakMaps и использовать их как age.set(this, 20), или написать небольшую оболочку и использовать его по-другому, как privateProps.set(this, 'age', 0).
Конфиденциальность этого подхода теоретически может быть нарушена путем вмешательства в глобальный WeakMapобъект. Тем не менее, весь JavaScript может быть сломан искаженными глобалами. Наш код уже построен на предположении, что этого не происходит.
(Этот метод также может быть реализован Map, но WeakMapлучше, потому что Mapон создаст утечки памяти, если вы не будете очень осторожны, и для этого они не отличаются друг от друга.)
Полуответ: символы в области видимости
Символ - это тип примитивного значения, которое может служить именем свойства. Вы можете использовать метод переменной области видимости, чтобы создать личный символ, а затем сохранить личные данные в this[mySymbol].
Конфиденциальность этого метода может быть нарушена с помощью Object.getOwnPropertySymbols, но это несколько неловко сделать.
Пример:
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)`.
Полуответ: Подчеркивает
Старый по умолчанию, просто используйте публичное свойство с префиксом подчеркивания. Хотя это соглашение никоим образом не является частной собственностью, оно достаточно распространено, и оно хорошо справляется с тем, что читатели должны относиться к собственности как к частной, что часто выполняет свою работу. В обмен на это мы получаем подход, который легче читать, легче печатать и быстрее.
Пример:
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.
Вывод
Начиная с ES2017, до сих пор нет идеального способа сделать частную собственность. Различные подходы имеют свои плюсы и минусы. Переменные в области видимости являются действительно приватными; WeakMaps с областями видимости являются очень приватными и более практичными, чем переменные с областями видимости; Символы с определенной областью являются достаточно частными и достаточно практичными; подчеркивания часто бывают достаточно приватными и очень практичными.