Користувачі: #
-приватні поля
Передмова:
Compile час і час виконання конфіденційність
#
-Приватні поля забезпечують час компіляції і час виконання секретність, яка не є «зламати». Це механізм запобігання доступу до члена з-за корпусу класу будь-яким прямим способом .
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-коди.
Зовнішні бібліотеки
Автори бібліотеки можуть рефакторно #
-привласнити ідентифікатори, не спричиняючи неполадок зміни клієнтів. Користувачі бібліотеки з іншого боку захищені від доступу до внутрішніх полів.
API JS не містить #
-приватні поля
Вбудовані функції JS та методи ігнорують #
-приватні поля. Це може призвести до більш передбачуваного вибору властивостей під час виконання. Приклади: 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
члена за допомогою виходу люка :
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
може забезпечити кращу ефективність роботи в деяких випадках зниження рівня (див. тут ).
- Наразі в 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
}
}
Джерела