#
Варианты использования: -приватные поля
Предисловие:
Конфиденциальность во время компиляции и во время выполнения
#
Поля -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
}
}
источники