aboutsummaryrefslogtreecommitdiff
path: root/files/fr/web/javascript/reference/classes/private_class_fields/index.md
blob: 9d1187b01dcaeaa7bac013c02d8e25ab71721f54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
---
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>", "<em>hash names</em>" en anglais), 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 worl​d"</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 worl​d✨"
</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="/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>