#Варианты использования: -приватные поля
Предисловие:
Конфиденциальность во время компиляции и во время выполнения
#Поля -private обеспечивают конфиденциальность во время компиляции и во время выполнения, что не является "взломанным". Это механизм, предотвращающий доступ к члену вне тела класса любым прямым способом .
class A {
#a: number;
constructor(a: number) {
this.#a = a;
}
}
let foo: A = new A(42);
foo.#a; // error, not allowed outside class bodies
(foo as any).#bar; // still nope.
Безопасное наследование классов
#-приватные поля получают уникальную область видимости. Иерархии классов могут быть реализованы без случайной перезаписи частных свойств с одинаковыми именами.
class A {
#a = "a";
fnA() { return this.#a; }
}
class B extends A {
#a = "b";
fnB() { return this.#a; }
}
const b = new B();
b.fnA(); // returns "a" ; unique property #a in A is still retained
b.fnB(); // returns "b"
Компилятор TS, к счастью, выдает ошибку, когда privateсвойства могут быть перезаписаны (см. Этот пример ). Но из-за особенностей функции времени компиляции все еще возможно во время выполнения, учитывая, что ошибки компиляции игнорируются и / или испускается код JS.
Внешние библиотеки
Авторы библиотеки могут рефакторировать #-приватные идентификаторы, не вызывая серьезных изменений для клиентов. Пользователи библиотеки с другой стороны защищены от доступа к внутренним полям.
JS API опускает #-приватные поля
Встроенные функции и методы JS игнорируют #поля -private. Это может привести к более предсказуемому выбору свойств во время выполнения. Примеры: Object.keys, Object.entries, JSON.stringify, for..inпетли и другие ( пример кода , см также Мэтта Bierner в ответ ):
class Foo {
#bar = 42;
baz = "huhu";
}
Object.keys(new Foo()); // [ "baz" ]
Варианты использования: privateключевое слово
Предисловие:
Доступ к внутреннему API класса и состоянию (конфиденциальность только во время компиляции)
privateчлены класса являются обычными свойствами во время выполнения. Мы можем использовать эту гибкость для доступа к внутреннему API-интерфейсу класса или состоянию извне. Для выполнения проверок компилятором @ts-ignoreмогут использоваться такие механизмы, как утверждения типа, динамический доступ к свойствам или другие.
Пример с утверждением типа ( as/ <>) и anyтипизированной переменной:
class A {
constructor(private a: number) { }
}
const a = new A(10);
a.a; // TS compile error
(a as any).a; // works
const casted: any = a; casted.a // works
TS даже позволяет динамический доступ к свойству privateчлена с помощью escape-люка :
class C {
private foo = 10;
}
const res = new C()["foo"]; // 10, res has type number
Где может иметь смысл частный доступ? (1) модульные тесты, (2) ситуации отладки / регистрации или (3) другие сложные сценарии с внутренними классами проекта (открытый список).
Доступ к внутренним переменным немного противоречив, иначе вы бы не сделали их privateв первую очередь. В качестве примера, модульные тесты должны быть черными / серыми блоками с закрытыми полями, скрытыми как детали реализации. На практике, тем не менее, могут существовать подходы от случая к случаю.
Доступно во всех средах ES
privateМодификаторы TS могут использоваться со всеми целями ES. #-приватные поля доступны только для target ES2015/ ES6или выше. В ES6 + WeakMapиспользуется внутри как реализация нижнего уровня (см. Здесь ). Собственные #-приватные поля в настоящее время требуют target esnext.
Согласованность и совместимость
Команды могут использовать рекомендации по кодированию и правилам линтера, чтобы обеспечить использование в privateкачестве единственного модификатора доступа. Это ограничение может помочь в согласованности и избежать путаницы с #нотацией -private поля обратно совместимым образом.
При необходимости свойства параметров (сокращение назначения конструктора) являются ограничителем показа. Их можно использовать только с privateключевым словом, и пока нет планов по их реализации для #полей -private.
Другие причины
privateможет обеспечить лучшую производительность во время выполнения в некоторых случаях понижения (см. здесь ).
- До сих пор в TS нет жестких методов закрытого класса.
- Некоторым людям нравится
privateнотация ключевых слов 😊.
Обратите внимание на оба
Оба подхода создают некий номинальный или фирменный тип во время компиляции.
class A1 { private a = 0; }
class A2 { private a = 42; }
const a: A1 = new A2();
// error: "separate declarations of a private property 'a'"
// same with hard private fields
Кроме того, оба разрешают доступ между экземплярами: экземпляр класса Aможет обращаться к закрытым членам других Aэкземпляров:
class A {
private a = 0;
method(arg: A) {
console.log(arg.a); // works
}
}
источники