Користувачі: # -приватні поля
Передмова:
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
}
}
Джерела