Przypadki użycia: #
-prywatne pola
Przedmowa:
Prywatność w czasie kompilacji i wykonywania
#
Pola prywatna zapewnić kompilacji i prywatność run-time, która nie jest „hackable”. Jest to mechanizm, aby uniemożliwić dostęp do członka z zewnątrz ciała klasy w żaden bezpośredni sposób .
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.
Bezpieczne dziedziczenie klas
#
-prywatne pola mają unikalny zasięg. Hierarchie klas mogą być implementowane bez przypadkowego nadpisywania własności prywatnych o takich samych nazwach.
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"
Na szczęście kompilator TS emituje błąd, gdy private
istnieje ryzyko , że właściwości zostaną zastąpione (patrz ten przykład ). Ale ze względu na naturę funkcji czasu kompilacji wszystko jest nadal możliwe w czasie wykonywania, biorąc pod uwagę błędy kompilacji są ignorowane i / lub wykorzystywany jest kod JS.
Biblioteki zewnętrzne
Autorzy bibliotek mogą refaktoryzować #
-prywatne identyfikatory bez powodowania przełomowej zmiany dla klientów. Użytkownicy biblioteki z drugiej strony są chronieni przed dostępem do pól wewnętrznych.
Interfejs API JS pomija #
pola -prywatne
Wbudowane funkcje i metody JS ignorują #
pola -prywatne. Może to skutkować bardziej przewidywalnym wyborem właściwości w czasie wykonywania. Przykłady: Object.keys
, Object.entries
, JSON.stringify
, for..in
pętla i inni ( przykładowy kod ; patrz także Matt Bierner za odpowiedź ):
class Foo {
#bar = 42;
baz = "huhu";
}
Object.keys(new Foo()); // [ "baz" ]
Przypadki użycia: private
słowo kluczowe
Przedmowa:
Dostęp do interfejsu API klasy wewnętrznej i stanu (prywatność tylko podczas kompilacji)
private
członkowie klasy są właściwościami konwencjonalnymi w czasie wykonywania. Możemy wykorzystać tę elastyczność, aby uzyskać dostęp do wewnętrznego interfejsu API klasy lub stanu z zewnątrz. Aby spełnić wymagania kompilatora, mechanizmy takie jak asercje typu, dynamiczny dostęp do właściwości lub @ts-ignore
mogą być używane między innymi.
Przykład z asercją typu ( as
/ <>
) i any
przypisaniem zmiennej typu:
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 pozwala nawet na dynamiczny dostęp do właściwości private
elementu z klapą ewakuacyjną :
class C {
private foo = 10;
}
const res = new C()["foo"]; // 10, res has type number
Gdzie prywatny dostęp może mieć sens? (1) testy jednostkowe, (2) sytuacje debugowania / rejestrowania lub (3) inne zaawansowane scenariusze przypadków z klasami wewnętrznymi projektu (lista otwarta).
Dostęp do zmiennych wewnętrznych jest trochę sprzeczny - inaczej nie stworzyłbyś ich private
w pierwszej kolejności. Na przykład testy jednostkowe powinny być czarnymi / szarymi skrzynkami z prywatnymi polami ukrytymi jako szczegóły implementacji. W praktyce jednak mogą istnieć odpowiednie podejścia w poszczególnych przypadkach.
Dostępne we wszystkich środowiskach ES
private
Modyfikatory TS można stosować ze wszystkimi celami ES. #
-prywatne pola są dostępne tylko dla target
ES2015
/ ES6
lub wyższej. W ES6 + WeakMap
jest wykorzystywany wewnętrznie jako implementacja niższego poziomu (patrz tutaj ). Natywne #
pola prywatne obecnie wymagają target
esnext
.
Spójność i kompatybilność
Zespoły mogą korzystać ze wskazówek dotyczących kodowania i reguł linijek, aby wymusić użycie private
jako jedynego modyfikatora dostępu. To ograniczenie może pomóc zachować spójność i uniknąć pomylenia z #
notacją pola -prywatnego w sposób zgodny z poprzednimi wersjami.
W razie potrzeby właściwości parametru (skrót konstruktora) są ogranicznikiem pokazu. Można ich używać tylko ze private
słowem kluczowym i nie ma jeszcze planów ich wdrożenia dla #
pól -prywatnych.
Inne powody
private
może zapewnić lepszą wydajność w czasie wykonywania w niektórych przypadkach obniżania poziomu (patrz tutaj ).
- Do tej pory nie ma twardych metod klasy prywatnej w TS.
- Niektórym bardziej podoba się
private
notacja słowa kluczowego 😊.
Uwaga na oba
Oba podejścia tworzą rodzaj nominalnego lub markowego typu w czasie kompilacji.
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
Oba umożliwiają także dostęp między instancjami: instancja klasy A
może uzyskać dostęp do prywatnych członków innych A
instancji:
class A {
private a = 0;
method(arg: A) {
console.log(arg.a); // works
}
}
Źródła