Casi d'uso: #
-campi privati
Prefazione:
Privacy in fase di compilazione e runtime
#
-private field forniscono privacy in fase di compilazione e runtime, che non è "hackerabile". È un meccanismo per impedire l'accesso a un membro esterno al corpo della classe in qualsiasi modo diretto .
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.
Eredità di classe sicura
#
i campi privati hanno un ambito unico. Le gerarchie di classi possono essere implementate senza sovrascritture accidentali di proprietà private con nomi uguali.
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"
Il compilatore TS genera fortunatamente un errore quando le private
proprietà rischiano di essere sovrascritte (vedi questo esempio ). Ma a causa della natura di una funzione di compilazione, tutto è ancora possibile in fase di esecuzione, dato che gli errori di compilazione vengono ignorati e / o utilizzati codice JS.
Biblioteche esterne
Gli autori delle biblioteche possono eseguire il refactoring di #
identificatori privati senza causare una rottura sostanziale per i client. Gli utenti della biblioteca dall'altra parte sono protetti dall'accesso ai campi interni.
L'API JS omette i #
campi privati
Le funzioni e i metodi JS integrati ignorano i #
campi privati. Ciò può comportare una selezione delle proprietà più prevedibile in fase di esecuzione. Esempi: Object.keys
, Object.entries
, JSON.stringify
, for..in
loop e altri ( esempio di codice ; vedi anche di Matt Bierner risposta ):
class Foo {
#bar = 42;
baz = "huhu";
}
Object.keys(new Foo()); // [ "baz" ]
Casi d'uso: private
parola chiave
Prefazione:
Accesso all'API e allo stato della classe interna (privacy solo in fase di compilazione)
private
i membri di una classe sono proprietà convenzionali in fase di esecuzione. Possiamo usare questa flessibilità per accedere all'API interna della classe o allo stato dall'esterno. Al fine di soddisfare i controlli del compilatore, meccanismi come asserzioni di tipo, accesso dinamico alle proprietà o @ts-ignore
possono essere utilizzati tra gli altri.
Esempio con asserzione di tipo ( as
/ <>
) e any
assegnazione di variabile digitata:
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 consente persino l'accesso dinamico alle proprietà di un private
membro con un tratteggio di escape :
class C {
private foo = 10;
}
const res = new C()["foo"]; // 10, res has type number
Dove può avere senso l'accesso privato? (1) test unitari, (2) situazioni di debug / registrazione o (3) altri scenari di casi avanzati con classi interne al progetto (elenco aperto).
L'accesso alle variabili interne è un po 'contraddittorio, altrimenti non le avresti fatte private
in primo luogo. Per fare un esempio, si suppone che i test unitari siano scatole nere / grigie con campi privati nascosti come dettagli di implementazione. In pratica, tuttavia, potrebbero esserci approcci validi da caso a caso.
Disponibile in tutti gli ambienti ES
I private
modificatori TS possono essere utilizzati con tutti i target ES. #
i campi privati sono disponibili solo per target
ES2015
/ ES6
o successivi. In ES6 +, WeakMap
viene utilizzato internamente come implementazione di livello inferiore (vedere qui ). I #
campi privati nativi attualmente richiedono target
esnext
.
Coerenza e compatibilità
I team potrebbero utilizzare le linee guida per la codifica e le regole di linter per imporre l'utilizzo private
come unico modificatore di accesso. Questa restrizione può aiutare con coerenza ed evitare confusione con la #
notazione di campo privata in modo compatibile con le versioni precedenti.
Se necessario, le proprietà dei parametri (abbreviazione di assegnazione del costruttore) sono un blocco dello spettacolo. Possono essere usati solo con private
parole chiave e non ci sono ancora piani per implementarli per i #
campi privati.
Altri motivi
private
potrebbe fornire prestazioni di runtime migliori in alcuni casi di livellamento (vedere qui ).
- Fino ad ora non ci sono metodi di classe privata disponibili in TS.
- Ad alcune persone piace la
private
notazione della parola chiave 😊.
Nota su entrambi
Entrambi gli approcci creano un tipo di tipo nominale o di marca al momento della compilazione.
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
Inoltre, entrambi consentono l'accesso tra istanze: un'istanza di classe A
può accedere a membri privati di altre A
istanze:
class A {
private a = 0;
method(arg: A) {
console.log(arg.a); // works
}
}
fonti