Cas d'utilisation: - #champs privés
Préface:
Confidentialité à la compilation et à l' exécution
#-Les champs privés fournissent une confidentialité au moment de la compilation et de l' exécution, qui n'est pas "piratable". C'est un mécanisme pour empêcher l'accès à un membre de l'extérieur du corps de classe de quelque manière directe .
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.
Héritage de classe sécurisé
#-Les champs privés ont une portée unique. Les hiérarchies de classes peuvent être implémentées sans écraser accidentellement des propriétés privées de noms égaux.
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"
Le compilateur TS émet heureusement une erreur, lorsque les privatepropriétés risquent d'être écrasées (voir cet exemple ). Mais en raison de la nature d'une fonctionnalité au moment de la compilation, tout est encore possible au moment de l'exécution, étant donné que les erreurs de compilation sont ignorées et / ou le code JS émis est utilisé.
Bibliothèques externes
Les auteurs de bibliothèque peuvent refactoriser les #identifiants privés sans provoquer de changement majeur pour les clients. Les utilisateurs de la bibliothèque de l'autre côté sont protégés contre l'accès aux champs internes.
L'API JS omet les #champs privés
Les fonctions et méthodes JS intégrées ignorent les #champs privés. Cela peut entraîner une sélection de propriétés plus prévisible au moment de l'exécution. Exemples: Object.keys, Object.entries, JSON.stringify, for..inboucle et autres ( exemple de code , voir aussi Matt Bierner réponse ):
class Foo {
#bar = 42;
baz = "huhu";
}
Object.keys(new Foo()); // [ "baz" ]
Cas d'utilisation: privatemot - clé
Préface:
Accès à l'API et à l'état de la classe interne (confidentialité au moment de la compilation uniquement)
privateles membres d'une classe sont des propriétés classiques au moment de l'exécution. Nous pouvons utiliser cette flexibilité pour accéder à l'API interne de classe ou à l'état de l'extérieur. Afin de satisfaire les vérifications du compilateur, des mécanismes tels que les assertions de type, l'accès aux propriétés dynamiques ou @ts-ignorepeuvent être utilisés entre autres.
Exemple avec assertion de type ( as/ <>) et anyaffectation de variable typée:
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 permet même un accès dynamique aux propriétés d'un privatemembre avec un hayon :
class C {
private foo = 10;
}
const res = new C()["foo"]; // 10, res has type number
Où l'accès privé peut-il avoir un sens? (1) des tests unitaires, (2) des situations de débogage / journalisation ou (3) d'autres scénarios de cas avancés avec des classes internes au projet (liste ouverte).
L'accès aux variables internes est un peu contradictoire - sinon vous ne les auriez pas faites privateen premier lieu. Pour donner un exemple, les tests unitaires sont supposés être des boîtes noires / grises avec des champs privés cachés comme détails d'implémentation. En pratique cependant, il peut y avoir des approches valables d'un cas à l'autre.
Disponible dans tous les environnements ES
Les privatemodificateurs TS peuvent être utilisés avec toutes les cibles ES. #-Les champs privés ne sont disponibles que pour target ES2015/ ES6ou plus. Dans ES6 +, WeakMapest utilisé en interne comme implémentation de niveau inférieur (voir ici ). Les #champs natifs- privés nécessitent actuellement target esnext.
Cohérence et compatibilité
Les équipes peuvent utiliser des directives de codage et des règles de linter pour imposer l'utilisation de privatecomme seul modificateur d'accès. Cette restriction peut aider à la cohérence et éviter toute confusion avec la #notation de champ privé d'une manière rétrocompatible.
Si nécessaire, les propriétés des paramètres (raccourci d'affectation du constructeur) sont un bouchon d'exposition. Ils ne peuvent être utilisés qu'avec des privatemots clés et il n'est pas encore prévu de les implémenter pour les #champs privés.
Autres raisons
privatepeut fournir de meilleures performances d'exécution dans certains cas de mise à niveau inférieur (voir ici ).
- Jusqu'à présent, aucune méthode de classe privée dure n'est disponible dans TS.
- Certaines personnes préfèrent la
privatenotation par mots clés 😊.
Remarque sur les deux
Les deux approches créent une sorte de type nominal ou de marque au moment de la compilation.
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
En outre, les deux autorisent l'accès inter-instances: une instance de classe Apeut accéder aux membres privés d'autres Ainstances:
class A {
private a = 0;
method(arg: A) {
console.log(arg.a); // works
}
}
Sources