| [ Web Proxy ] |
| Viewing: https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide/Equality_comparisons_and_sameness | [Back] [Original] |
Get to know MDN better
Cette page a t traduite partir de l'anglais par la communaut. Vous pouvez contribuer en rejoignant la communaut francophone sur MDN Web Docs.
JavaScript fournit trois oprations permettant de comparer des valeurs :
===,==,Object.is (ajout avec ECMAScript 2015).Ces trois oprations sont associes quatre algorithmes d'galit (depuis ES2015) :
La comparaison d'galit stricte (===)
Array.indexOf et Array.lastIndexOf et la sensibilit la casseSameValueZero (l'galit de valeurs nulles)
TypedArray et ArrayBuffer et par les oprations associes Map et Set. Depuis ES2016, cet algorithme est galement utilis par String.includes et Array.includesSameValue (l'galit de valeurs)
Selon la comparaison qu'on souhaite effectuer, on choisira une de ces oprations.
En rsum :
==) effectuera une conversion des deux lments comparer avant d'effectuer la comparaison===) effectuera la mme comparaison mais sans conversion pralable (elle renverra toujours false si les types des deux valeurs compares sont diffrents)Object.is() se comportera comme l'galit stricte sauf pour les valeurs NaN, -0 et +0 : pour Object.is(), -0 et +0 seront diffrents mais on aura Object.is(NaN, NaN) qui sera true. (Gnralement, quand on compare NaN avec NaN en utilisant l'galit stricte ou l'galit faible, cela donne false afin de respecter la norme IEEE 754.)On notera que pour ces trois oprations, la comparaison s'effectue sur les valeurs des lments qu'on compare, aucune de ces oprations ne permet de comparer la structure des paramtres. Pour des objets non primitifs, x et y qui ont la mme structure mais qui sont des objets distincs, chacune des oprations prsentes ci-avant sera value false.
===
==
Object.is et quand utiliser l'galit stricte
===L'galit stricte compare deux valeurs et teste leur galit. Aucune des valeurs n'est convertie implicitement en une autre valeur avant que la comparaison soit effectue. Si les valeurs sont types diffremment, elles sont considres comme diffrentes. Si les valeurs sont de mme type et ne sont pas des nombres, elles sont considres gales si elles ont la mme valeur. Si les deux valeurs sont des nombres, elles sont gales si elles ont la mme valeur et que cette valeur n'est pas NaN ou si l'une vaut +0 et l'autre -0.
var num = 0;
var obj = new String("0");
var str = "0";
console.log(num === num); // true
console.log(obj === obj); // true
console.log(str === str); // true
console.log(num === obj); // false
console.log(num === str); // false
console.log(obj === str); // false
console.log(null === undefined); // false
console.log(obj === null); // false
console.log(obj === undefined); // false
Ce test d'galit stricte est presque toujours la meilleure des oprations considrer pour ces tests. Except pour les nombres, la smantique utilise est simple : une valeur est uniquement gale elle-mme. En ce qui concerne les nombres, il y a deux cas aux limites considrer. Le premier cas concerne le nombre zro positif ou ngatif. Cela peut tre utile dans la reprsentation de problmes mathmatiques mais ne constitue pas une diffrence pour de nombreuses situations : le test d'galit stricte considre que ce sont les mmes valeurs. Le second cas concerne la valeur n'est pas un nombre , NaN (pour not a number en anglais) permettant de reprsenter certaines entits mathmatiques : la somme des deux infinis (positif et ngatif) par exemple. Le test d'galit stricte considre que NaN est diffrent de toutes les valeurs, y compris lui-mme. (N.B. : Le seul cas de figure pour lequel on a (x !== x) qui renvoie true est lorsque x vaut NaN.)
==Le test d'galit faible compare deux valeurs aprs les avoir converties en valeurs d'un mme type. Une fois converties (la conversion peut s'effectuer pour l'une ou les deux valeurs), la comparaison finale est la mme que celle effectue par ===. L'galit faible est symtrique : A == B aura toujours la mme signification que B == A pour toute valeur de A et B.
La comparaison d'galit est effectue comme suit pour des oprandes de diffrents types :
| Oprande B | |||||||
|---|---|---|---|---|---|---|---|
| Undefined | Null | Number | String | Boolean | Object | ||
| Oprande A | Undefined | true |
true |
false |
false |
false |
false |
| Null | true |
true |
false |
false |
false |
false |
|
| Number | false |
false |
A === B |
A === ToNumber(B) |
A === ToNumber(B) |
A == ToPrimitive(B) |
|
| String | false |
false |
ToNumber(A) === B |
A === B |
ToNumber(A) === ToNumber(B) |
A == ToPrimitive(B) |
|
| Boolean | false |
false |
ToNumber(A) === B |
ToNumber(A) === ToNumber(B) |
A === B |
false |
|
| Object | false |
false |
ToPrimitive(A) == B |
ToPrimitive(A) == B |
ToPrimitive(A) == ToNumber(B) |
|
|
Dans le tableau ci-dessus, l'expression ToNumber(A) correspond une tentative de convertir l'argument en un nombre avant la comparaison. Le rsultat obtenu est quivalent +A (l'oprateur unaire +). ToPrimitive(A) correspond une tentative de convertir l'argument en une valeur primitive grce plusieurs mthodes comme A.toString et A.valueOf.
Selon ECMAScript, au sens de l'galit faible, tous les objets sont diffrents de undefined et de null. Cependant, la plupart des navigateurs autorisent, dans certains contextes, unensemble restreint d'objets (notamment l'objet document.all), agir comme s'ils mulaient la valeur undefined. L'galit faible est un de ces contextes. Pour tous les autres cas, un objet ne sera jamais approximativement gal undefined ou null.
var num = 0;
var obj = new String("0");
var str = "0";
console.log(num == num); // true
console.log(obj == obj); // true
console.log(str == str); // true
console.log(num == obj); // true
console.log(num == str); // true
console.log(obj == str); // true
console.log(null == undefined); // true
// Les deux assertions qui suivent sont fausses
// sauf dans certains cas exceptionnels
console.log(obj == null);
console.log(obj == undefined);
Certains dveloppeurs considrent que ce n'est jamais une bonne ide d'utiliser l'galilt faible. Le rsultat d'une comparaison utilisant l'galit stricte est plus simple apprhender et prdire, de plus il n'y a aucune conversion implicite ce qui rend le test plus rapide.
L'galit de valeurs rpond un dernier cas d'utilisation : savoir si deux valeurs sont fonctionnellement identiques pour tout contexte. (Ce cas d'utilisation est un exemple du principe de substitution de Liskov). On retrouve ce cas lorsqu'on essaie de changer une proprit immuable :
// Ajouter la proprit immuable NEGATIVE_ZERO au constructor Number.
Object.defineProperty(Number, "NEGATIVE_ZERO", {
value: -0,
writable: false,
configurable: false,
enumerable: false,
});
function attemptMutation(v) {
Object.defineProperty(Number, "NEGATIVE_ZERO", { value: v });
}
Object.defineProperty lancera une exception pour tout changement de la proprit qui serait rellement un changement. Rien ne se passera si aucun changement n'est ncessaire. Ainsi, si v vaut -0, aucun changement n'est ncessaire et il n'y aura pas d'erreur. Mais si v vaut +0, Number.NEGATIVE_ZERO n'aurait plus la mme valeur immuable. De faon interne l'implmentation, la nouvelle valeur est compare avec la valeur courante en utilisant une galit de valeurs.
L'galit de valeurs peut tre teste grce la mthode Object.is.
On utilise la mme galit que l'galit de valeur et on considre que +0 et -0 sont gaux.
Selon ES5, la comparaison effectue par == est dcrite dans la section 11.9.3 sur l'algorithme d'galit abstraite (Abstract Equality Algorithm). La comparaison donne par === est dcrite dans la section 11.9.6 sur l'algorithme d'galit stricte (Strict Equality Algorithm). Ces documents sont en anglais mais sont tout fait abordables, ne pas hsiter les consulter (conseil : d'abord commencer par l'algorithme d'galit stricte). ES5 dcrit galement, dans la section 9.12 sur l'algorithme SameValue, l'opration utilise en interne par le moteur JavaScript. Cet algorithme est principalement bas sur l'algorithme d'galit stricte : 11.9.6.4 et 9.12.4 diffrent en ce qui concerne les nombres. ES6 (ECMAScript 2015) permet d'utiliser cet algorithme grce la mthode Object.is.
Dans ces documents, on peut voir que l'algorithme d'galit stricte est un sous-ensemble de l'algorithme d'galit abstraite (exception faite de la vrification du type) car 11.9.6.27 correspond exactement 11.9.3.1.af.
Avant ES6 (ECMAScript 2015), il tait courant de dire que l'galit stricte avec le triple gal tait une version amliore de l'galit faible (double gal) et vice versa. En effet, l'galit faible ajoute une tape de conversion des types qui n'est pas fournie par l'galit stricte (ce qui permet d'avoir 6 == "6"). On peut aussi dire que l'galit stricte est une version amliore de l'galit simple car elle ajoute une fonctionnalit de vrification des types. Selon votre approche et votre problme, une de ces galits se prtera mieux la rsolution.
Cependant, ce modle de penses ne peut pas tre tendu avec l'arrive d'Object.is avec ES6 (ECMAScript 2015). En effet Object.is() n'est pas plus faible que l'galit faible ou plus stricte que l'galit stricte et il n'est pas non plus quelque part entre les deux. Dans le tableau de comparaison ci-aprs, on voit que la diffrence provient avant tout de la faon dont Object.is gre NaN. On note ici que si Object.is(NaN, NaN) valait false, on pourrait dire qu'Object.is() est plus stricte que == ou === car elle distingue -0 et +0. Cependant, ce n'est pas le cas et on a bien Object.is(NaN,NaN) qui vaut true. C'est pour cette raison qu'il faut considrer Object.is selon ses caractristiques spcifiques plutt que comme une version plus faible ou plus stricte des autres oprateurs d'galit.
| x | y | == |
=== |
Object.is |
SameValueZero |
|---|---|---|---|---|---|
undefined |
undefined |
true |
true |
true |
true |
null |
null |
true |
true |
true |
true |
true |
true |
true |
true |
true |
true |
false |
false |
true |
true |
true |
true |
'toto' |
'toto' |
true |
true |
true |
true |
0 |
0 |
true |
true |
true |
true |
+0 |
-0 |
true |
true |
false |
true |
+0 |
0 |
true |
true |
true |
true |
-0 |
0 |
true |
true |
false |
true |
0 |
false |
true |
false |
false |
false |
"" |
false |
true |
false |
false |
false |
"" |
0 |
true |
false |
false |
false |
'0' |
0 |
true |
false |
false |
false |
'17' |
17 |
true |
false |
false |
false |
[1, 2] |
'1,2' |
true |
false |
false |
false |
new String('toto') |
'toto' |
true |
false |
false |
false |
null |
undefined |
true |
false |
false |
false |
null |
false |
false |
false |
false |
false |
undefined |
false |
false |
false |
false |
false |
{ toto: 'truc' } |
{ toto: 'truc' } |
false |
false |
false |
false |
new String('toto') |
new String('toto') |
false |
false |
false |
false |
0 |
null |
false |
false |
false |
false |
0 |
NaN |
false |
false |
false |
false |
'toto' |
NaN |
false |
false |
false |
false |
NaN |
NaN |
false |
false |
true |
true |
Object.is et quand utiliser l'galit stricteEn plus de la faon dont Object.is traite NaN, la spcificit d'Object.is() rside dans sa faon de traiter les valeurs proches de zro. Dans des cas d'utilisation o on a besoin d'effectuer de la mta-programmation, notamment pour imiter certaines caractristiques de Object.defineProperty. Si le scnario d'utilisation ne ncessite pas ce comportement, il est conseill d'utiliser ===. Mme si on souhaite pouvoir comparer NaN avec lui-mme et que ce test vaille true, il sera plus simple d'utiliser la mthode isNaN disponible avec les versions antrieures d'ECMAScript. En effet, cela vite d'avoir traiter des cas plus complexes o il faudrait grer les signes des zros dans les diffrentes comparaisons.
Voici une liste (non exhaustive) d'oprateurs et de mthodes natives qui peuvent entraner l'apparition des valeurs -0 et +0 dans le code :
- (ngation unaire)Si on prend l'oppos de 0, on aura, bien entendu, -0. Cependant, avec les expressions, cela peut faire que la valeur -0 se glisse dans les variables sans qu'on s'en rende compte. Par exemple :
let forceArrt = obj.masse * -obj.vitesse;
Si obj.vitesse vaut 0 (ou est valu 0), un -0 sera introduit, ce qui fera que forceArrt pourra tre ngative.
Math.atan2, Math.ceil, Math.pow, Math.roundCes mthodes peuvent introduire -0 dans une expression lors de leur valuation, mme si -0 ne faisait pas partie des paramtres. Par exemple, si on utilise Math.pow() pour lever -Infinity une puissance ngative, on obtiendra -0 pour une puissance impaire. Pour plus de dtails, voir la documentation de chaque mthode.
Math.floor, Math.max, Math.min, Math.sin, Math.sqrt, Math.tanCes mthodes peuvent renvoyer -0 dans certains cas o -0 est pass en paramtre. Par exemple, Math.min(-0, +0) fournira -0. Pour plus de dtails, voir la documentation de chaque mthode.
~, <<, >>Chacun de ces oprateurs utilise l'algorithme ToInt32 interne au moteur JavaScript. tant donn qu'il n'y a qu'une seule reprsentation pour 0 sur les entiers exprims avec le type interne sur 32 bits, -0 ne sera pas invariant pour deux oprations symtriques : Object.is(~~(-0), -0) et Object.is(-0 << 2 >> 2, -0) renverront tous les deux false.
Si on utilise Object.is et qu'on ne souhaite pas grer les cas aux limites autour de zro, cela peut avoir des effet indsirs. En revanche, si on souhaite effectivement comparer -0 et +0, c'est la mthode adopter.
Cette page a t modifie le 2 dc. 2025 par les contributeurices du MDN.
Certaines parties de ce contenu sont protges par le droit d'auteur 19982026 des contributeurs individuels de mozilla.org. Contenu disponible sous une licence Creative Commons.
| Web Proxy Viewer | New URL | Original Page |