--- title: Variables de classe privés slug: Web/JavaScript/Reference/Classes/Private_class_fields tags: - Classe - Fonctionnalité du langage - JavaScript translation_of: Web/JavaScript/Reference/Classes/Private_class_fields --- <div>{{JsSidebar("Classes")}}</div> <div>Les propriétés de classe sont publiques par défaut et peuvent être lues et modifiées à l'extérieur de la classe. Cependant, <a href="https://github.com/tc39/proposal-class-fields">une proposition expérimentale</a>, permettant de définir des variables privées dans une classe avec le préfixe <code>#</code>, est disponible.</div> <h2 id="Syntaxe">Syntaxe</h2> <pre class="syntaxbox notranslate">class ClassWithPrivateField { #privateField } class ClassWithPrivateMethod { #privateMethod() { return 'hello world' } } class ClassWithPrivateStaticField { static #PRIVATE_STATIC_FIELD } </pre> <h2 id="Exemples">Exemples</h2> <h3 id="Champs_privés_statiques">Champs privés statiques</h3> <p>Les champs privés sont accessibles depuis le constructeur et depuis l'intérieur de la déclaration de la classe elle-même.</p> <p>La limitation des variables statiques ne pouvant être appelées que par des méthodes statiques tient toujours.</p> <pre class="brush: js notranslate">class ClassWithPrivateStaticField { static #PRIVATE_STATIC_FIELD static publicStaticMethod() { ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42 return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD } } console.assert(ClassWithPrivateStaticField.publicStaticMethod() === 42)</pre> <p>Les champs statiques privés sont ajoutés au constructeur de la classe au moment de l'évaluation de classe..</p> <p>Il y a une restriction de provenance sur les champs statiques privés. Seule la classe qui a défini un champ statique privé peut y accéder.</p> <p>Ceci peut conduire à un comportement inattendu lors de l'utilisation de <strong><code>this</code></strong>.</p> <pre class="brush: js notranslate">class BaseClassWithPrivateStaticField { static #PRIVATE_STATIC_FIELD static basePublicStaticMethod() { this.#PRIVATE_STATIC_FIELD = 42 return this.#PRIVATE_STATIC_FIELD } } class SubClass extends BaseClassWithPrivateStaticField { } let error = null try { SubClass.basePublicStaticMethod() } catch(e) { error = e} console.assert(error instanceof TypeError) </pre> <h3 id="Champs_dinstance_privés">Champs d'instance privés</h3> <p>Les champs d'instance privés sont déclarés avec des <strong>noms</strong> à <strong># </strong>(prononcés "<em>noms à hash</em>", <span class="st">"<em>hash names</em>" en anglais</span>), qui sont des identifieurs préfixés par <code>#</code>. Le <code>#</code> fait partie du nom lui-même. Il est utilisé tant pour la déclaration que pour l'accès.</p> <p>L'encapsulation est forcée par le langage. C'est une erreur de syntaxe que de faire référence aux noms à <code>#</code> en dehors de leur portée.</p> <pre class="brush: js notranslate">class ClassWithPrivateField { #privateField constructor() { this.#privateField = 42 this.#randomField = 666 // Erreur de syntaxe } } const instance = new ClassWithPrivateField() instance.#privateField === 42 // Erreur de syntaxe </pre> <h3 id="Méthodes_Privées">Méthodes Privées</h3> <h4 id="Méthodes_statiques_privées">Méthodes statiques privées</h4> <p>Comme leur équivalents publics, les méthodes statiques privées sont appelées dans la classe elle-même, pas dans les instances de la classe. Comme les champs statiques privés, elles ne sont accessibles que depuis l'intérieur de la déclaration de la classe.</p> <p>Les méthodes statiques privées peuvent être des fonctions génératrices, asynchrones et génératrices asynchrones.</p> <pre class="brush: js notranslate">class ClassWithPrivateStaticMethod { static #privateStaticMethod() { return 42 } static publicStaticMethod1() { return ClassWithPrivateStaticMethod.#privateStaticMethod(); } static publicStaticMethod2() { return this.#privateStaticMethod(); } } console.assert(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42); console.assert(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42); </pre> <p>Cela peut conduire à un comportement inattendu lors de l'utilisation de <strong><code>this</code></strong>. Dans l'exemple suivant, <code>this</code> fait référence à la classe <code>Derived</code> (pas à la classe <code>Base</code>) lorsqu'on essaie d'appeler <code>Derived.publicStaticMethod2()</code>, et fait ainsi apparaître la même "restriction de provenance" que mentionné ci-dessus :</p> <pre class="brush: js notranslate">class Base { static #privateStaticMethod() { return 42; } static publicStaticMethod1() { return Base.#privateStaticMethod(); } static publicStaticMethod2() { return this.#privateStaticMethod(); } } class Derived extends Base {} console.log(Derived.publicStaticMethod1()); // 42 console.log(Derived.publicStaticMethod2()); // TypeError </pre> <h4 id="Méthodes_dinstance_privées">Méthodes d'instance privées</h4> <p>Les méthodes d'instance privées sont des méthodes disponibles dans les instances de classe privées, dont l'accès est restreint de la même manière que les champs d'instance privés.</p> <pre class="brush: js notranslate">class ClassWithPrivateMethod { #privateMethod() { return 'hello world' } getPrivateMessage() { return this.#privateMethod() } } const instance = new ClassWithPrivateMethod() console.log(instance.getPrivateMessage()) // expected output: "hello world"</pre> <p>Les méthodes d'instance privées peuvent être des fonctions génératrices, asynchones ou génératrices asynchrones. Des accesseurs (getters) et des mutateurs (setters) privés sont aussi posibles :</p> <pre class="brush: js notranslate">class ClassWithPrivateAccessor { #message get #decoratedMessage() { return `✨${this.#message}✨` } set #decoratedMessage(msg) { this.#message = msg } constructor() { this.#decoratedMessage = 'hello world' console.log(this.#decoratedMessage) } } new ClassWithPrivateAccessor(); // expected output: "✨hello world✨" </pre> <h2 id="Spécifications">Spécifications</h2> <table class="standard-table"> <thead> <tr> <th scope="col">Spécification</th> </tr> </thead> <tbody> <tr> <td>{{SpecName('Public and private instance fields', '#prod-FieldDefinition', 'FieldDefinition')}}</td> </tr> </tbody> </table> <h2 id="Compatibilité_des_navigateurs">Compatibilité des navigateurs</h2> <p>{{Compat("javascript.classes.private_class_fields")}}</p> <h2 id="Voir_aussi">Voir aussi</h2> <ul> <li><a href="https://wiki.developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Classes/Class_fields">Champs de classe publiques</a></li> <li><a href="https://rfrn.org/~shu/2018/05/02/the-semantics-of-all-js-class-elements.html">The Semantics of All JS Class Elements</a></li> </ul>