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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
|
---
title: L'égalité en JavaScript
slug: Web/JavaScript/Guide/Égalité_en_JavaScript
tags:
- Advanced
- Guide
- JavaScript
- Operators
translation_of: Web/JavaScript/Equality_comparisons_and_sameness
translation_of_original: Web/JavaScript/Guide/Sameness
---
<p>{{jsSidebar("JavaScript Guide")}}</p>
<p>EcmaScript6 possède trois outils pour déterminer si deux valeurs x et y sont « égales ». Il y a l'égalité simple (deux signes égal) (<a href="/fr/docs/JavaScript/Reference/R%C3%A9f%C3%A9rence_JavaScript/Op%C3%A9rateurs/Op%C3%A9rateurs_de_comparaison"><code>==</code></a>), l'égalité stricte (trois signes égal) (<a href="/fr/docs/JavaScript/Reference/R%C3%A9f%C3%A9rence_JavaScript/Op%C3%A9rateurs/Op%C3%A9rateurs_de_comparaison"><code>===</code></a>), et la méthode <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/is"><code>Object.is</code></a>. (Cette méthode a été ajoutée avec ES6. Les opérateurs d'égalité simple et stricte étaient présents en JavaScript avant ES6 et ont conservé leur comportement.)</p>
<h2 id="Un_aperçu">Un aperçu</h2>
<p>Voici comment utiliser chacun de ces outils de comparaisons :</p>
<pre class="brush:js">x == y</pre>
<pre class="brush:js">x === y</pre>
<pre class="brush:js">Object.is(x, y)</pre>
<p>En résumé : l'opérateur d'égalité simple effectuera une conversion de type entre les objets comparés, l'opérateur d'égalité stricte n'effectuera pas de conversion avant de comparer les objets (<code>false</code> est renvoyé automatiquement si les types sont différents), enfin <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/is"><code>Object.is</code></a> se comportera de la même façon que l'opérateur d'égalité stricte avec des règles supplémentaires pour les valeurs <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/NaN"><code>NaN</code></a>, <code>-0</code> et <code>+0</code>. <code>Object.is(-0, +0) </code>ne sera pas vérifié et <code>Object.is(NaN, NaN)</code> sera vrai. (Généralement, quand on compare <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/NaN"><code>NaN</code></a> et <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/NaN"><code>NaN</code></a>, on obtient le résultat <code>false</code> car la norme IEEE 754 indique que ce comportement est celui attendu pour l'égalité simple ou stricte.)</p>
<p>Cette égalité ne s'applique qu'aux types de données primitifs, aucune des méthodes présentées ci-avant ne permet de comparer la structure de deux objets. Si deux objets x et y possèdent la même structure mais que ce sont des objets distincts, chacune de ces méthodes renverra le résultat <code>false</code>.</p>
<p>Ainsi :</p>
<pre class="brush:js">let x = { valeur: 17 };
let y = { valeur: 17 };
console.log(Object.is(x, y)); // false;
console.log(x === y); // false
console.log(x == y); // false</pre>
<h2 id="Les_égalités_simples_strictes_et_les_valeurs_identiques">Les égalités simples, strictes et les valeurs identiques</h2>
<p>Les comparaisons effectuées par les opérateurs d'égalité simple et d'égalité stricte sont décrites par EcmaScript5 : l'algorithme de l'opérateur <a href="/fr/docs/JavaScript/Reference/R%C3%A9f%C3%A9rence_JavaScript/Op%C3%A9rateurs/Op%C3%A9rateurs_de_comparaison"><code>==</code></a> est décrit dans la <a href="http://ecma-international.org/ecma-262/5.1/#sec-11.9.3" title="http://ecma-international.org/ecma-262/5.1/#sec-11.9.3">section 11.9.3 (en anglais)</a> et l'algorithme de l'opérateur <a href="/fr/docs/JavaScript/Reference/R%C3%A9f%C3%A9rence_JavaScript/Op%C3%A9rateurs/Op%C3%A9rateurs_de_comparaison"><code>=== </code></a>est décrit dans la <a href="http://ecma-international.org/ecma-262/5.1/#sec-11.9.6" title="http://ecma-international.org/ecma-262/5.1/#sec-11.9.6">section 11.9.6 (en anglais)</a>. Ces deux algorithmes sont expliqués de façon simple et concise, il est préferable de lire le deuxième algorithme avant le premier. ES5 décrit également l'algorithme utilisé en interne par le moteur JavaScript : <a href="http://ecma-international.org/ecma-262/5.1/#sec-9.12" title="http://ecma-international.org/ecma-262/5.1/#sec-9.12">section 9.12, The SameValue Algorithm (en anglais)</a>. Ce dernier algorithme est très proche de celui utilisé pour l'égalité stricte, ils différent de par leurs gestions différentes des nombres représentés sous forme d'objets <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Number"><code>Number</code></a>. <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/is"><code>Object.is</code></a> n'est que la retranscription de cet algorithme, utilisable depuis ES6.</p>
<p>Excepté pour la conversion implicite, on peut voir que, pour les opérateurs d'égalité simple et stricte, l'algorithme d'égalité stricte est un sous-ensemble de l'égalité simple car 11.9.6.2-7 correspond à 11.9.3.1.a-f.</p>
<h2 id="Comprendre_le_sens_des_différentes_égalités">Comprendre le sens des différentes égalités</h2>
<p>Avant ES6, on pouvait penser que l'égalité stricte était une version « améliorée » de l'égalité simple, ou vice-versa. Par exemple, dans certains cas, on peut trouver que l'égalité simple est plus souple que l'égalité stricte car elle effectue une conversion des types (ce qui permet de vérifier <code>6 == "6"</code>). Au contraire, on peut trouver que l'égalité stricte est « meilleure » que l'égalité simple car il est nécessaire que les deux opérandes soient du même type. L'utilité de chaque opérateur dépend du cadre dans lequel on l'utilise.</p>
<p><a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/is"><code>Object.is</code></a>, en revanche, n'est pas plus souple ou plus stricte que ces égalités. Il n'est pas non plus un « intermédiaire » entre ces deux opérateurs. <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/is"><code>Object.is</code></a> diffère dans sa façon de gérer la valeur numérique spéciale <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/NaN"><code>NaN</code></a>. D'une certaine façon, <code><a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/is">Object.is</a></code> se différencie en fonction de ses caractéristiques spéciales sur <code><a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/NaN">NaN</a></code> et -0 et +0.</p>
<table class="standard-table">
<caption>
Opérateurs d'égalité</caption>
<thead>
<tr>
<th scope="col" style="text-align: center;">x</th>
<th scope="col" style="text-align: center;">y</th>
<th scope="col" style="width: 10em; text-align: center;"><code>==</code></th>
<th scope="col" style="width: 10em; text-align: center;"><code>===</code></th>
<th scope="col" style="width: 10em; text-align: center;"><code>Object.is</code></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>undefined</code></td>
<td><code>undefined</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
</tr>
<tr>
<td><code>null</code></td>
<td><code>null</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
</tr>
<tr>
<td><code>true</code></td>
<td><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
</tr>
<tr>
<td><code>false</code></td>
<td><code>false</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
</tr>
<tr>
<td><code>"toto"</code></td>
<td><code>"toto"</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
</tr>
<tr>
<td><code>{ toto: "truc" }</code></td>
<td><code>x</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
</tr>
<tr>
<td><code>0</code></td>
<td><code>0</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
</tr>
<tr>
<td><code>+0</code></td>
<td><code>-0</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>0</code></td>
<td><code>false</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>""</code></td>
<td><code>false</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>""</code></td>
<td><code>0</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>"0"</code></td>
<td><code>0</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>"17"</code></td>
<td><code>17</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>new String("toto")</code></td>
<td><code>"toto"</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>null</code></td>
<td><code>undefined</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>null</code></td>
<td><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>undefined</code></td>
<td><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>{ toto: "truc" }</code></td>
<td><code>{ toto: "truc" }</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>new String("toto")</code></td>
<td><code>new String("toto")</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>0</code></td>
<td><code>null</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>0</code></td>
<td><code>NaN</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>"toto"</code></td>
<td><code>NaN</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
</tr>
<tr>
<td><code>NaN</code></td>
<td><code>NaN</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td>
<td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td>
</tr>
</tbody>
</table>
<h2 id="Dans_quels_cas_utiliser_Object.is_ou_l'opérateur_d'égalité_stricte">Dans quels cas utiliser <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/is"><code>Object.is</code></a> ou l'opérateur d'égalité stricte</h2>
<p>En dehors du traîtement effectué pour <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/NaN"><code>NaN</code></a>, <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/is"><code>Object.is</code></a> s'avère utile lorsqu'on manipule des valeurs très proches de 0 (parfois utilisées pour la métaprogrammation et notamment pour les descripteurs de propriétés et qu'on souhaite reproduire certaines caractéristiques de <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/defineProperty"><code>Object.defineProperty</code></a>). Si on n'a pas ce cas de figure à gérer, il est conseillé d'utiliser <a href="/fr/docs/JavaScript/Reference/R%C3%A9f%C3%A9rence_JavaScript/Op%C3%A9rateurs/Op%C3%A9rateurs_de_comparaison"><code>===</code></a>. Même dans l'éventualité où on devrait gérer une comparaison entre deux valeurs <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/NaN"><code>NaN</code></a> il est souvent plus facile de traiter le cas particulier en utilisant la fonction <a href="/fr/docs/JavaScript/R%C3%A9f%C3%A9rence_JavaScript/R%C3%A9f%C3%A9rence_JavaScript/Fonctions_globales/isNaN"><code>isNaN</code></a> présente dans les anciennes versions d'ECMAScript.</p>
<p>Voici une liste (non exhaustive) des méthodes et opérateurs qui pourraient entraîner une apparition des valeurs <code>-0</code> et <code>+0</code> :</p>
<dl>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_arithmétiques#N.C3.A9gation_unaire_(-)"><code>- (négation unaire)</code></a></dt>
</dl>
<dl>
<dd>
<p>Il peut sembler évident que l'opposé de <code>0</code> est <code>-0</code> mais lorsque que cette opération est réalisée dans une expression, il est plus facile d'identifier la transformation qui s'est effectuée. Par exemple :</p>
<pre class="brush:js">let forceFrottement = obj.masse * -obj.vitesse</pre>
<p>Si <code>obj.vitesse </code>vaut <code>0</code>, on aura <code>-0</code> comme résultat du calcul, et c'est cette valeur qui sera assignée à <code>forceFrottement</code></p>
</dd>
</dl>
<dl>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/atan2"><code>Math.atan2</code></a></dt>
<dt>
<a href="/fr/docs/JavaScript/Reference/Objets_globaux/Math/ceil"><code>Math.ceil</code></a></dt>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/pow"><code>Math.pow</code></a></dt>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/round"><code>Math.round</code></a></dt>
</dl>
<dl>
<dd>
La valeur <code>-0</code> peut être produite par ces méthodes (et donc introduite dans une expression qui les comportent), même dans le cas où <code>-0</code> n'est pas un argument. Par exemple, si on utilise <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/pow"><code>Math.pow</code></a> pour calculer <code>-<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Infinity">Infinity</a></code> à une puissance entière impaire et négative, on obtiendra <code>-0</code>. Voir les différentes pages sur ces méthodes pour plus d'informations.</dd>
</dl>
<dl>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/floor"><code>Math.floor</code></a></dt>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/max"><code>Math.max</code></a></dt>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/min"><code>Math.min</code></a></dt>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/sin"><code>Math.sin</code></a></dt>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/sqrt"><code>Math.sqrt</code></a></dt>
<dt>
<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/tan"><code>Math.tan</code></a></dt>
</dl>
<dl>
<dd>
Ces méthodes peuvent produire la valeur <code>-0</code> si c'est un des paramètres de la fonction. Par exemple, <code>Math.min(-0, +0)</code> vaudra <code>-0</code>. Voir les différentes pages sur ces méthodes pour plus d'informations.</dd>
</dl>
<dl>
<dt>
<code><a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_binaires">~</a></code></dt>
<dt>
<code><a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_binaires"><<</a></code></dt>
<dt>
<code><a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_binaires">>></a></code></dt>
<dd>
Chacun de ces opérateurs utilise l'algorithme ToInt32. Or, il n'y a qu'une seule représentation possible pour 0 sous forme d'un entier sur 32 bits, c'est pourquoi <code>-0</code> ne pourra pas être « conservé » par une combinaison de ces opérations (même si cette combinaison est équivalente, logiquement, à une identité). Par exemple <code>Object.is(~~(-0), -0)</code> et <code>Object.is(-0 << 2 >> 2, -0)</code> produiront la valeur <code>false</code>.</dd>
</dl>
<p>Il peut être dangereux d'utiliser <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/is" title="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/is"><code>Object.is</code></a> quand on ne souhaite pas différencier les deux valeurs <code>-0</code> et <code>+0</code>. En revanche, si on souhaite distinguer ces deux valeurs, cette fonction est idéale.</p>
|