Quel opérateur égal (== vs ===) doit être utilisé dans les comparaisons JavaScript?

5665

J'utilise JSLint pour passer par JavaScript, et il renvoie de nombreuses suggestions à remplacer ==(deux signes égaux) par ===(trois signes égaux) lorsque vous faites des choses comme comparer à l' idSele_UNVEHtype.value.length == 0intérieur d'une ifdéclaration.

Y a-t-il un avantage de performance à remplacer ==par ===?

Toute amélioration des performances serait la bienvenue car il existe de nombreux opérateurs de comparaison.

Si aucune conversion de type n'a lieu, y aurait-il un gain de performances par rapport à ==?

bcasp
la source
134
À qui il pourrait être intéressé par le même sujet === vs ==, mais en PHP, peut lire ici: stackoverflow.com/questions/2401478/why-is-faster-than-in-php/…
Marco Demaio
257
Juste au cas où quelqu'un se demanderait en 2012: ===c'est bien plus rapide que ==. jsperf.com/comparison-of-comparisons
Ry-
25
@minitech il devrait être comme il ne fait pas de conversion de type
Umur Kontacı
19
@minitech, je doute que quiconque accélère sensiblement son application en utilisant ===over ==. En fait, le benchmark ne montre pas de grande différence entre les deux sur les navigateurs modernes. Personnellement, j'utilise généralement ==partout sauf si j'ai vraiment besoin d'une stricte égalité.
laurent
5
Voici la partie de la conférence JS The Good Parts de Crockford où il discute des opérateurs ===et ==: youtube.com/… Si cela ne joue pas, c'est à 15h20
davidhiggins

Réponses:

6487

L'opérateur d'égalité stricte ( ===) se comporte de manière identique à l'opérateur d'égalité abstraite ( ==) sauf qu'aucune conversion de type n'est effectuée et que les types doivent être identiques pour être considérés comme égaux.

Référence: Tutoriel Javascript: Opérateurs de comparaison

L' ==opérateur comparera pour l'égalité après avoir effectué toutes les conversions de type nécessaires . L' ===opérateur ne fera pas la conversion, donc si deux valeurs ne sont pas du même type ===, il retournera simplement false. Les deux sont tout aussi rapides.

Pour citer l'excellent JavaScript de Douglas Crockford : The Good Parts ,

JavaScript a deux ensembles d'opérateurs d'égalité: ===et !==, et leurs mauvais jumeaux ==et !=. Les bons fonctionnent comme vous vous en doutez. Si les deux opérandes sont du même type et ont la même valeur, alors ===produit trueet !==produit false. Les mauvais jumeaux font la bonne chose lorsque les opérandes sont du même type, mais s'ils sont de types différents, ils tentent de contraindre les valeurs. les règles par lesquelles ils le font sont compliquées et immémoriales. Voici quelques-uns des cas intéressants:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

Tableau de comparaison de l'égalité

Le manque de transitivité est alarmant. Mon conseil est de ne jamais utiliser les jumeaux maléfiques. À la place, utilisez toujours ===et !==. Toutes les comparaisons qui viennent d'être montrées produisent falseavec l' ===opérateur.


Mise à jour:

Un bon point a été soulevé par @Casebash dans les commentaires et dans la réponse de @Phillipe Laybaert concernant les objets. Pour les objets, ==et ===agissez de manière cohérente les uns avec les autres (sauf dans un cas particulier).

var a = [1,2,3];
var b = [1,2,3];

var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };

var e = "text";
var f = "te" + "xt";

a == b            // false
a === b           // false

c == d            // false
c === d           // false

e == f            // true
e === f           // true

Le cas spécial est lorsque vous comparez une primitive avec un objet qui est évalué à la même primitive, en raison de sa méthode toStringou valueOf. Par exemple, considérons la comparaison d'une primitive de chaîne avec un objet chaîne créé à l'aide du Stringconstructeur.

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

Ici, l' ==opérateur vérifie les valeurs des deux objets et retourne true, mais le ===voit qu'ils ne sont pas du même type et revient false. Laquelle est correcte? Cela dépend vraiment de ce que vous essayez de comparer. Mon conseil est de contourner complètement la question et de ne pas utiliser le Stringconstructeur pour créer des objets chaîne à partir de littéraux chaîne.

Référence
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3

Bill le lézard
la source
237
=== n'est pas plus rapide si les types sont les mêmes. Si les types ne sont pas identiques, === sera plus rapide car il n'essaiera pas de faire la conversion.
Bill the Lizard
521
=== ne sera jamais plus lent que ==. Ils vérifient tous les deux le type, donc === ne fait rien de plus par rapport à ==, mais le contrôle de type peut permettre à === de se terminer plus tôt lorsque les types ne sont pas les mêmes.
Bill the Lizard
246
Remplacer tout == /! = Par === /! == augmente la taille du fichier js, il faudra alors plus de temps pour le charger. :)
Marco Demaio
92
"... les règles par lesquelles ils le font sont compliquées et inoubliables ..." Maintenant, de telles déclarations vous font vous sentir si en sécurité lors de la programmation ...
Johan
47
De Crockford: "Le manque de transitivité est alarmant." Si vous développez un logiciel et ne trouvez pas le manque de transitivité alarmant chez un opérateur de comparaison, ou si la comparaison de vitesse entre == et === ou la taille du fichier / le temps de chargement ont priorité dans votre esprit sur le déterminisme transitif du comportement d'un opérateur de comparaison, vous peut-être besoin de revenir en arrière et de recommencer.
jinglesthula
1144

Utilisation de l' ==opérateur ( égalité )

true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2;  //true, because "2" is converted to 2 and then compared

Utilisation de l' ===opérateur ( identité )

true === 1; //false
"2" === 2;  //false

En effet, l' opérateur d'égalité saisit la ==contrainte , ce qui signifie que l'interpréteur essaie implicitement de convertir les valeurs avant de comparer.

D'un autre côté, l' opérateur d'identité ===ne fait pas de coercition de type , et donc ne convertit pas les valeurs lors de la comparaison, et est donc plus rapide (comme selon ce test de référence JS ) car il saute une étape.

Kalpesh Rajai
la source
9
@Software Monkey: pas pour les types de valeurs (nombre, booléen, ...)
Philippe Leybaert
34
Puisque personne n'a mentionné la table d'égalité Javascript, la voici: dorey.github.io/JavaScript-Equality-Table
blaze
6
Dans la première déclaration, êtes-vous sûr que «vrai» est converti en 1 et non 1 converti en vrai?
Shadi Namrouti
2
D'où viennent les termes «égalité» et «identité»? La norme n'utilise pas ces termes. Il appelle ==«égalité abstraite» et il appelle ===«égalité stricte». Certes, appeler ==toute sorte d '"égalité" est à mon humble avis, car il n'est pas transitif, mais pourquoi chicaner? Je prends plus de problème avec "l'identité" cependant; Je pense que ce terme est assez trompeur, bien qu'il "fonctionne". Mais sérieusement, qui a inventé le terme «identité»? Je recherche la norme et je ne la trouve pas.
Ray Toal
1
"Identité" n'est pas le bon mot. Les comparaisons d'identité dans toutes les langues que j'ai utilisées signifient une dans le même objet , c'est-à-dire que les deux variables de référence pointent non seulement vers des entités équivalentes, mais vers la même entité.
Inigo
724

Une représentation picturale intéressante de la comparaison d'égalité entre ==et ===.

Source: http://dorey.github.io/JavaScript-Equality-Table/


var1 === var2

Lors de l'utilisation ===pour les tests d'égalité JavaScript, tout est tel quel. Rien n'est converti avant d'être évalué.

Évaluation de l'égalité de === dans JS


var1 == var2

Lors de l'utilisation ==pour les tests d'égalité JavaScript, certaines conversions géniales ont lieu.

Évaluation de l'égalité de == dans JS

Morale de l'histoire:

À utiliser ===sauf si vous comprenez parfaitement les conversions qui ont lieu avec ==.

Accroc
la source
3
@mfeineest vous voulez dire === ou! == au lieu de == ou! =. Je ne veux pas confondre les nouveaux codeurs;)
katalin_2003
2
d'après mon expérience, l'utilisation de trois égaux peut causer des problèmes et doit être évitée à moins d'être bien comprise. deux égaux produisent de bien meilleurs résultats parce que 99% du temps, je ne veux vraiment pas que les types soient égaux.
vsync
13
@vsync: Si vous ne voulez vraiment pas les types soient égaux , vous devez utiliser trois égaux !
SNag
7
La seule exception: vous pouvez utiliser en toute sécurité x == nullpour vérifier si xest nullou undefined.
Andy
1
@ user648026: La question concerne l' égalité comparaison avec ==vs ===. Les majuscules et les minuscules sont de toute façon inégales et reviendront falseavec les opérateurs ==et ===. En outre, des mots - clés true, false, undefined, null, Infinityexistent dans JS dans un seul cas, et ne peuvent pas être utilisés dans les cas supérieurs ou mixtes.
SNag
609

Dans les réponses ici, je n'ai rien lu sur ce que signifie l' égalité . Certains diront que cela ===signifie égal et du même type , mais ce n'est pas vraiment vrai. Cela signifie en fait que les deux opérandes font référence au même objet , ou dans le cas de types de valeur, ont la même valeur .

Prenons donc le code suivant:

var a = [1,2,3];
var b = [1,2,3];
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Pareil ici:

var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Ou même:

var a = { };
var b = { };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Ce comportement n'est pas toujours évident. Il y a plus dans l'histoire qu'être égal et être du même type.

La règle est:

Pour les types de valeur (nombres):
a === b renvoie vrai siaetbont la même valeur et sont du même type

Pour les types de référence:
a === b renvoie true siaetbréférence exactement le même objet

Pour les chaînes:
a === b renvoie true siaetbsont les deux chaînes et contiennent exactement les mêmes caractères


Cordes: le cas particulier ...

Les chaînes ne sont pas des types de valeur, mais en Javascript, elles se comportent comme des types de valeur, elles seront donc "égales" lorsque les caractères de la chaîne sont identiques et lorsqu'ils sont de la même longueur (comme expliqué dans la troisième règle)

Maintenant ça devient intéressant:

var a = "12" + "3";
var b = "123";

alert(a === b); // returns true, because strings behave like value types

Mais qu'en est-il?:

var a = new String("123");
var b = "123";

alert(a === b); // returns false !! (but they are equal and of the same type)

Je pensais que les chaînes se comportaient comme des types de valeur? Eh bien, cela dépend de qui vous demandez ... Dans ce cas, a et b ne sont pas du même type. aest de type Object, tandis que best de type string. N'oubliez pas que la création d'un objet chaîne à l'aide du Stringconstructeur crée quelque chose de type Objectqui se comporte comme une chaîne la plupart du temps .

Philippe Leybaert
la source
6
activa: Je voudrais préciser que les chaînes ne sont tellement égales que lorsqu'elles sont littérales. new String ("abc") === "abc" est faux (selon mes recherches).
Lawrence Dol
3
new Number() == "0". Aussi dans Firefox:(function(){}) == "function () {\n}"
Thomas Eding
3
Merci d'avoir expliqué pourquoi new String("123") !== "123". Ce sont des types différents. Simple, mais déroutant.
styfle
21
Stringles objets se comportent comme des chaînes comme tout autre objet . new Stringne doit jamais être utilisé, car cela ne crée pas de vraies chaînes. Une vraie chaîne et peut être faite avec des littéraux de chaîne ou appeler Stringen fonction sans new , par exemple:String(0); //"0", Real string, not an object
Esailija
6
Mais dans les cas que vous avez détaillés, l'opérateur "==" se comporte exactement de la même manière.
Yaron Levi
270

Permettez-moi d'ajouter ce conseil:

En cas de doute, lisez les spécifications !

ECMA-262 est la spécification d'un langage de script dont JavaScript est un dialecte. Bien sûr, dans la pratique, il importe davantage de savoir comment se comportent les navigateurs les plus importants qu'une définition ésotérique de la façon dont quelque chose est censé être géré. Mais il est utile de comprendre pourquoi la nouvelle chaîne ("a")! == "a" .

Veuillez me laisser expliquer comment lire les spécifications pour clarifier cette question. Je vois que dans ce sujet très ancien, personne n'a eu de réponse pour l'effet très étrange. Donc, si vous pouvez lire une spécification, cela vous aidera énormément dans votre profession. C'est une compétence acquise. Continuons donc.

La recherche du fichier PDF pour === m'amène à la page 56 de la spécification: 11.9.4. L'opérateur Strict Equals (===) , et après avoir pataugé dans les spécifications, je trouve:

11.9.6 L'algorithme de
comparaison stricte d'égalité La comparaison x === y, où x et y sont des valeurs, produit vrai ou faux . Une telle comparaison est effectuée comme suit:
  1. Si Type (x) est différent de Type (y), retournez false .
  2. Si Type (x) n'est pas défini, retournez true .
  3. Si Type (x) est Null, retournez true .
  4. Si Type (x) n'est pas Number, passez à l'étape 11.
  5. Si x est NaN , retournez false .
  6. Si y est NaN , retournez false .
  7. Si x est la même valeur numérique que y, retournez true .
  8. Si x est +0 et y est -0, retourne vrai .
  9. Si x est −0 et y est +0, retourne vrai .
  10. Retournez faux .
  11. Si Type (x) est String, retournez true si x et y sont exactement la même séquence de caractères (même longueur et mêmes caractères aux positions correspondantes); sinon, retournez false .
  12. Si Type (x) est booléen, retournez vrai si x et y sont tous les deux vrais ou tous les deux faux ; sinon, retournez false .
  13. Retour vraisi x et y se réfèrent au même objet ou s'ils se réfèrent à des objets joints entre eux (voir 13.1.2). Sinon, retournez false .

L'intérêt est l'étape 11. Oui, les chaînes sont traitées comme des types de valeur. Mais cela n'explique pas pourquoi la nouvelle chaîne ("a")! == "a" . Avons-nous un navigateur non conforme à ECMA-262?

Pas si vite!

Vérifions les types d'opérandes. Essayez-le par vous-même en les enveloppant dans typeof () . Je trouve que la nouvelle chaîne ("a") est un objet, et l'étape 1 est utilisée: retourne faux si les types sont différents.

Si vous vous demandez pourquoi une nouvelle chaîne ("a") ne renvoie pas de chaîne, que diriez-vous d'un exercice de lecture d'une spécification? S'amuser!


Aidiakapi a écrit ceci dans un commentaire ci-dessous:

De la spécification

11.2.2 Le nouvel opérateur :

Si Type (constructeur) n'est pas Object, lève une exception TypeError.

En d'autres termes, si String ne serait pas de type Object, il ne pourrait pas être utilisé avec le nouvel opérateur.

new renvoie toujours un Object, même pour les constructeurs String . Et hélas! La valeur sémantique des chaînes (voir étape 11) est perdue.

Et cela signifie enfin: new String ("a")! == "a" .

nalply
la source
Le résultat de Type (x) est supposé être le même que typeof?
Dfr
@nalply Je ne comprends pas exactement l'anxiété suscitée par ce comportement new String('x'), car je n'ai jamais vu de code dans la nature qui utilise des objets wrapper primitifs, et je ne pense pas qu'il y ait beaucoup de bonnes raisons, surtout pas de nos jours. Avez-vous déjà rencontré du code qui le fait?
Andy
@Andy le problème est du code tiers malveillant ou simplement bâclé, alors vous ne pouvez pas supposer que personne n'utilise new String().
2018
Si c'est bâclé, === est la façon dont vous le saurez. Si c'est malveillant, je pense que new String()c'est probablement le moindre de vos soucis. Je comprends la préoccupation en théorie, mais encore une fois, avez-vous des exemples concrets? Pour moi, c'est comme la vieille anxiété que quelqu'un pouvait fixer undefinedà une autre valeur.
Andy
Je ne sais pas où vous avez obtenu ceci, mais votre algorithme de comparaison se trompe à l'étape 2. La section "7.2.15 Comparaison stricte d'égalité" vérifie d'abord si les types sont les mêmes, si oui s'ils sont Number. Sinon, la section "7.2.12 SameValueNonNumber (x, y)" est utilisée.
Rusty Core
101

En PHP et JavaScript, c'est un opérateur d'égalité stricte. Cela signifie qu'il comparera à la fois le type et les valeurs.

Shiki
la source
10
@David: correct. C'est pourquoi cette réponse est inexacte (voire erronée)
Philippe Leybaert
7
@David var a = {}, b = {}; a == brenvoie false.
nyuszika7h
6
Oui: deux objets différents avec le même type et la même valeur se comparent faux, c'est-à-dire que cette réponse est tout simplement fausse. Pourquoi a-t-il 50 votes positifs?
alexis
4
Je me rends compte que c'est vieux, mais clarifier pourquoi cette réponse est toujours "correcte" est parce que dans l'exemple var a = {}, b = {};Alors que les deux aet best en effet à la fois un objet, mais ils n'ont pas la même valeur, techniquement parlant. Ce sont des instances différentes . Notez que la comparaison des instances se comporte différemment de la comparaison des primitives. Ce qui ajoute probablement à cette confusion. Vous verrez un comportement de comparaison similaire si vous utilisez une version d'instance de types de données primitifs. Par exemple new String('asdf')ou new Number(5). Ex: new Number(5) == new Number(5)est faux, même s'ils ont la même valeur.
Norman Breau
1
Nous oublions tous qu'une référence à un objet est en fait un type de valeur, car il s'agit d'un pointeur vers un emplacement mémoire. La comparaison d'objets ne consiste pas à comparer la «valeur de l'objet» mais à savoir si les deux pointeurs sont identiques, ce qui signifie qu'ils référencent le même emplacement de mémoire. C'est une différence très subtile dans la comparaison des types, car l'opérateur "===" doit vraiment dire "si le type, la valeur et la référence à l'objet en mémoire sont les mêmes".
Stokely
101

J'ai testé cela dans Firefox avec Firebug en utilisant un code comme celui-ci:

console.time("testEquality");
var n = 0;
while(true) {
    n++;
    if(n==100000) 
        break;
}
console.timeEnd("testEquality");

et

console.time("testTypeEquality");
var n = 0;
while(true) {
    n++;
    if(n===100000) 
        break;
}
console.timeEnd("testTypeEquality");

Mes résultats (testés cinq fois chacun et moyennés):

==: 115.2
===: 114.4

Je dirais donc que la minuscule différence (c'est plus de 100 000 itérations, rappelez-vous) est négligeable. La performance n'est pas une raison de le faire ===. Tapez sécurité (enfin, aussi sûr que vous obtiendrez en JavaScript), et la qualité du code l'est.

Simon Scarfe
la source
3
Plus que la sécurité du type, vous voulez une exactitude logique - parfois vous voulez que les choses soient vraies en cas de ==désaccord.
rpjohnst
4
Maintenant, comment cela se compare-t-il quand il existe une véritable conversion de type pour l' ==opérateur? N'oubliez pas, c'est à ce moment-là qu'il y a une augmentation des performances.
Hubert OG
2
Différence MAJEURE lorsqu'elle est testée correctement pour les raisons susmentionnées de vérification plus rapide de l'inégalité de type uniquement. jsfiddle.net/4jhuxkb2
Doug Morrow
Vous mesurez les performances de quelque chose comme ça en opérations / seconde, pas un seul test dans un seul navigateur (un avec environ 5% de part de marché) en utilisant console.time () tout en utilisant un test qui ne prend pas de coercition de type (la raison entière il est plus lent) en compte. Il s'agit d'un test complètement dénué de sens. Vous avez raison de dire que les performances ne sont pas la raison de l'utilisation ===excessive, ==mais vous avez tort que leurs performances soient essentiellement égales et que vous penseriez que ce test prouve que, et que beaucoup d'autres personnes ont convenu, est totalement absurde pour moi.
Stephen M Irving
97

En JavaScript, cela signifie la même valeur et le même type.

Par exemple,

4 == "4" // will return true

mais

4 === "4" // will return false 
Dimitar
la source
87

Le === opérateur est appelé un opérateur de comparaison stricte, il ne diffère du == opérateur.

Prenons 2 vars a et b.

Pour que "a == b" soit évalué à vrai, a et b doivent avoir la même valeur .

Dans le cas de "a === b", a et b doivent avoir la même valeur et également le même type pour qu'il soit évalué comme vrai.

Prenez l'exemple suivant

var a = 1;
var b = "1";

if (a == b) //evaluates to true as a and b are both 1
{
    alert("a == b");
}

if (a === b) //evaluates to false as a is not the same type as b
{
    alert("a === b");
}

En résumé ; l'utilisation de l' opérateur == peut donner la valeur true dans des situations où vous ne le souhaitez pas, il est donc plus sûr d' utiliser l' opérateur === .

Dans le scénario d'utilisation à 90%, peu importe celui que vous utilisez, mais il est pratique de connaître la différence lorsque vous obtenez un comportement inattendu un jour.

Docteur Jones
la source
82

Pourquoi ==est-ce si imprévisible?

Qu'obtenez-vous lorsque vous comparez une chaîne vide ""avec le nombre zéro 0?

true

Oui, c'est vrai selon ==une chaîne vide et le nombre zéro sont en même temps.

Et ça ne s'arrête pas là, en voici un autre:

'0' == false // true

Les choses deviennent vraiment étranges avec les tableaux.

[1] == true // true
[] == false // true
[[]] == false // true
[0] == false // true

Puis plus bizarre avec des cordes

[1,2,3] == '1,2,3' // true - REALLY?!
'\r\n\t' == 0 // true - Come on!

Ça s'empire:

Quand est égal pas égal?

let A = ''  // empty string
let B = 0   // zero
let C = '0' // zero string

A == B // true - ok... 
B == C // true - so far so good...
A == C // **FALSE** - Plot twist!

Permettez-moi de le répéter:

(A == B) && (B == C) // true
(A == C) // **FALSE**

Et ce ne sont que les trucs fous que vous obtenez avec les primitives.

C'est un tout nouveau niveau de fou lorsque vous l'utilisez ==avec des objets.

À ce stade, vous vous demandez probablement ...

Pourquoi cela arrive-t-il?

Et bien c'est parce que contrairement à "triple equals" ( ===) qui vérifie juste si deux valeurs sont identiques.

==fait tout un tas d'autres trucs .

Il a un traitement spécial pour les fonctions, un traitement spécial pour les valeurs nulles, non définies, les chaînes, vous l'appelez.

C'est assez farfelu.

En fait, si vous essayez d'écrire une fonction qui fait quoi, ==cela ressemblera à ceci:

function isEqual(x, y) { // if `==` were a function
    if(typeof y === typeof x) return y === x;
    // treat null and undefined the same
    var xIsNothing = (y === undefined) || (y === null);
    var yIsNothing = (x === undefined) || (x === null);

    if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);

    if(typeof y === "function" || typeof x === "function") {
        // if either value is a string 
        // convert the function into a string and compare
        if(typeof x === "string") {
            return x === y.toString();
        } else if(typeof y === "string") {
            return x.toString() === y;
        } 
        return false;
    }

    if(typeof x === "object") x = toPrimitive(x);
    if(typeof y === "object") y = toPrimitive(y);
    if(typeof y === typeof x) return y === x;

    // convert x and y into numbers if they are not already use the "+" trick
    if(typeof x !== "number") x = +x;
    if(typeof y !== "number") y = +y;
    // actually the real `==` is even more complicated than this, especially in ES6
    return x === y;
}

function toPrimitive(obj) {
    var value = obj.valueOf();
    if(obj !== value) return value;
    return obj.toString();
}

Qu'est-ce que cela signifie?

Cela signifie que ==c'est compliqué.

Parce que c'est compliqué, il est difficile de savoir ce qui se passera lorsque vous l'utiliserez.

Ce qui signifie que vous pourriez vous retrouver avec des bugs.

La morale de l'histoire est donc ...

Rendez votre vie moins compliquée.

Utilisez ===au lieu de ==.

La fin.

Luis Perez
la source
Tu looseEqualas tort. Function == Function.toString()est vrai, mais looseEqual(Function, Function.toString())est faux. Je ne sais pas pourquoi vous filtrez les fonctions au début.
Oriol
@Oriol vous aviez raison, j'ai mis à jour le code pour tenir compte de cela, pour votre information, il ne suffisait pas de supprimer le filtre pour les "fonctions", mais les "fonctions" devaient être traitées différemment.
Luis Perez
Sachez que la spécification ne traite pas les fonctions différemment, ce ne sont que des objets. Le problème semble que vous vous fiez typeof x === "object"pour vérifier s'il s'agit d'un objet, mais `typeof ne fonctionne que pour les primitives non nulles. Vous pourriez être intéressé par ma liste de moyens appropriés pour vérifier si une valeur est un objet
Oriol
J'ai essayé de traiter les fonctions et les objets de la même manière, mais j'ai trouvé que les résultats étaient incorrects. Par exemple, si les fonctions étaient traitées comme des objets, la comparaison d'une fonction avec un objet qui implémente la fonction valueOf () ou toString () qui correspond à la fonction passerait, mais en réalité ce n'est pas le cas. Exemple: (function blah() { console.log("test"); }) != {valueOf:function(){return "function blah() { console.log(\"test\"); }";}}- consultez ce JS Fiddle qui exécute tous les tests: jsfiddle.net/luisperezphd/7k6gcn6g (il y a 1225 permutations de test)
Luis Perez
1
Vous avez raison, grandes observations, cela met l'accent sur le point principal qui ==fait beaucoup de choses, ce qui rend très difficile l'anticipation des résultats tout en ===étant beaucoup plus simple et prévisible, l'une des principales raisons ===étant le choix recommandé. (Je vais ajouter une note à la réponse en mentionnant votre point)
Luis Perez
81

===vérifie les mêmes côtés sont de type et de valeur égaux .


Exemple:

'1' === 1 // will return "false" because `string` is not a `number`

Exemple courant:

0 == ''  // will be "true", but it's very common to want this check to be "false"

Un autre exemple courant:

null == undefined // returns "true", but in most cases a distinction is necessary

Plusieurs fois , un typées contrôle serait à portée de main parce que vous ne vous inquiétez pas si la valeur est undefined, null, 0 ou""

vsync
la source
7
aussi,'string' !== 'number'
Homer
72

Diagramme d'exécution de Javascript pour une stricte égalité / Comparaison '==='

Javascript stricte égalité

Diagramme d'exécution de Javascript pour une égalité / comparaison non stricte '=='

Javascript non égalité

Samar Panda
la source
Je ne comprends pas pourquoi la stringflèche pointe vers la grande boîte grise, est-ce censé signifier que l'interrupteur transforme la chaîne en un nombre?
vsync
@vsync Il pointe vers l'option chaîne dans la case grise, c'est-à-dire chaîne -> # || NaN. Javascript n'est pas un langage de script de type, c'est-à-dire qu'il peut avoir n'importe quel type de variable. Donc, il est indiqué cette boîte grise.
Samar Panda, le
J'ai simplement demandé si c'était à des fins de casting car le stringest censé être comparé à un type number, donc l'interrupteur regarde ce à quoi la chaîne doit être comparée et transforme la chaîne en conséquence?
vsync
1
La grande boîte grise est ce ToNumberqui retournerait quand on lui donne différents types, donc si on lui donne une chaîne, elle ne choisira que la dernière option (et la convertira en un nombre). ==utilise ToNumberuniquement dans les cas string == numberou boolean == anythingci - dessus (et uniquement sur le string/ boolean). Cela signifie ==qu'ils ne se convertiront jamais undefinedou nullmême s'ils sont dans la zone grise. (Pour toute combinaison de l'un undefinedou de l'autre ou des nulldeux, ==sera toujours renvoyé true. En outre, si une valeur est à gauche ou à droite n'a pas d'importance, ==(et ===) retournera le même résultat.)
user2033427
55

JavaScript === vs == .

0==false   // true
0===false  // false, because they are of a different type
1=="1"     // true, auto type coercion
1==="1"    // false, because they are of a different type
Anik Islam Abhi
la source
54

Cela signifie l' égalité sans type de contrainte de type coercition signifie que JavaScript ne convertit pas automatiquement les autres types de données en types de données de chaîne

0==false   // true,although they are different types

0===false  // false,as they are different types

2=='2'    //true,different types,one is string and another is integer but 
            javaScript convert 2 to string by using == operator 

2==='2'  //false because by using === operator ,javaScript do not convert 
           integer to string 

2===2   //true because both have same value and same types 
Pop Catalin
la source
48

Dans un script typique, il n'y aura aucune différence de performances. Plus important peut être le fait que mille "===" est 1 Ko de plus que mille "==" :) Les profileurs JavaScript peuvent vous dire s'il y a une différence de performances dans votre cas.

Mais personnellement, je ferais ce que suggère JSLint. Cette recommandation n'est pas là en raison de problèmes de performances, mais parce que la contrainte de type signifie que ('\t\r\n' == 0)c'est vrai.

Constantin
la source
4
Pas toujours vrai. Avec la compression gzip, la différence serait presque négligeable.
Daniel X Moore
1
D'accord, mais mille "===" signifie aussi 10 milliers de lignes de code sinon donc plus ou moins 1kb ...;)
Jonny
Si vous
46

L'opérateur de comparaison égale == prête à confusion et doit être évité.

Si vous DEVEZ vivre avec, souvenez-vous des 3 choses suivantes:

  1. Il n'est pas transitif: (a == b) et (b == c) ne conduit pas à (a == c)
  2. Il est mutuellement exclusif de sa négation: (a == b) et (a! = B) contiennent toujours des valeurs booléennes opposées, avec tout a et b.
  3. En cas de doute, apprenez par cœur la table de vérité suivante:

TABLE DE VÉRITÉ DE L'OPÉRATEUR ÉGAL À JAVASCRIPT

  • Chaque ligne du tableau est un ensemble de 3 valeurs mutuellement «égales», ce qui signifie que 2 valeurs parmi elles sont égales en utilisant le signe égal == *

** ÉTRANGE: notez que deux valeurs quelconques sur la première colonne ne sont pas égales dans ce sens. **

''       == 0 == false   // Any two values among these 3 ones are equal with the == operator
'0'      == 0 == false   // Also a set of 3 equal values, note that only 0 and false are repeated
'\t'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\r'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\n'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\t\r\n' == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

null == undefined  // These two "default" values are not-equal to any of the listed values above
NaN                // NaN is not equal to any thing, even to itself.
CuongHuyTo
la source
39

Il est peu probable qu'il y ait une différence de performances entre les deux opérations dans votre utilisation. Il n'y a pas de conversion de type à effectuer car les deux paramètres sont déjà du même type. Les deux opérations auront une comparaison de types suivie d'une comparaison de valeurs.

Sean
la source
38

Oui! C'est important.

===L'opérateur en javascript vérifie la valeur ainsi que le type où, en tant ==qu'opérateur, vérifie simplement la valeur (saisit la conversion si nécessaire) .

entrez la description de l'image ici

Vous pouvez facilement le tester. Collez le code suivant dans un fichier HTML et ouvrez-le dans le navigateur

<script>

function onPageLoad()
{
    var x = "5";
    var y = 5;
    alert(x === 5);
};

</script>

</head>

<body onload='onPageLoad();'>

Vous obtiendrez « faux » en alerte. Maintenant, modifiez la onPageLoad()méthode pour que alert(x == 5);vous deveniez vraie .

Aniket Thakur
la source
33

=== L'opérateur vérifie l'égalité des valeurs ainsi que les types des variables.

== L'opérateur vérifie simplement l'égalité des valeurs des variables.

Niraj CHoubey
la source
32

C'est un test de vérification strict.

C'est une bonne chose surtout si vous vérifiez entre 0 et faux et nul.

Par exemple, si vous avez:

$a = 0;

Alors:

$a==0; 
$a==NULL;
$a==false;

Tout retourne vrai et vous ne le voudrez peut-être pas. Supposons que vous ayez une fonction qui peut retourner le 0ème index d'un tableau ou false en cas d'échec. Si vous vérifiez avec "==" false, vous pouvez obtenir un résultat déroutant.

Donc, avec la même chose que ci-dessus, mais un test strict:

$a = 0;

$a===0; // returns true
$a===NULL; // returns false
$a===false; // returns false
Daniel
la source
3
En JavaScript, c'est complètement faux et à tort incomplet. 0 != null. -1
Ry-
31

JSLint vous donne parfois des raisons irréalistes de modifier des éléments. ===a exactement les mêmes performances que== si les types sont déjà les mêmes.

Il est plus rapide uniquement lorsque les types ne sont pas identiques, auquel cas il n'essaie pas de convertir les types mais renvoie directement un faux.

Donc, à mon humble avis, humble avis JSLint peut être utilisé pour écrire du nouveau code, mais une sur-optimisation inutile doit être évitée à tout prix.

Cela signifie qu'il n'y a aucune raison de passer ==à ===un chèque commeif (a == 'test') lorsque vous le savez pour un fait qu'un ne peut être qu'une chaîne.

Modifier beaucoup de code de cette façon fait perdre du temps aux développeurs et aux réviseurs et ne donne rien.

cendres
la source
30

Simplement

==signifie la comparaison entre les opérandes avec type conversion

&

===signifie comparaison entre opérandes sans type conversion

La conversion de type en javaScript signifie que javaScript convertit automatiquement tous les autres types de données en types de données chaîne.

Par exemple:

123=='123'   //will return true, because JS convert integer 123 to string '123'
             //as we used '==' operator 

123==='123' //will return false, because JS do not convert integer 123 to string 
            //'123' as we used '===' operator 
Amit
la source
26

Un exemple simple est

2 == '2'  -> true, values are SAME because of type conversion.

2 === '2'  -> false, values are NOT SAME because of no type conversion.
Vikas
la source
25

Les 2 réponses les plus importantes mentionnées sont == signifie égalité et === signifie identité. Malheureusement, cette déclaration est incorrecte.

Si les deux opérandes de == sont des objets, ils sont comparés pour voir s'ils sont le même objet. Si les deux opérandes pointent vers le même objet, l'opérateur égal renvoie true. Sinon, les deux ne sont pas égaux.

var a = [1, 2, 3];  
var b = [1, 2, 3];  
console.log(a == b)  // false  
console.log(a === b) // false  

Dans le code ci-dessus, == et === deviennent faux car a et b ne sont pas les mêmes objets.

Cela signifie que si les deux opérandes de == sont des objets, == se comporte de la même manière que ===, ce qui signifie également identité. La différence essentielle de ces deux opérateurs concerne la conversion de type. == a une conversion avant de vérifier l'égalité, mais pas ===.

Harry He
la source
24

En règle générale, j'utiliserais généralement ===au lieu de ==(et !==au lieu de!= ).

Les raisons sont expliquées dans les réponses ci-dessus et Douglas Crockford est assez clair à ce sujet ( JavaScript: The Good Parts ).

Cependant, il existe une seule exception : == nullest un moyen efficace de vérifier si «est nul ou non défini»:

if( value == null ){
    // value is either null or undefined
}

Par exemple, jQuery 1.9.1 utilise ce modèle 43 fois, et le vérificateur de syntaxe JSHint fournit même leeqnull option relaxante pour cette raison.

À partir du guide de style jQuery :

Des contrôles d'égalité stricts (===) doivent être utilisés en faveur de ==. La seule exception est lors de la vérification de non défini et null par le biais de null.

// Check for both undefined and null values, for some important reason. 
undefOrNull == null;
mar10
la source
22

Le problème est que vous pourriez facilement avoir des ennuis car JavaScript a beaucoup de conversions implicites, ce qui signifie ...

var x = 0;
var isTrue = x == null;
var isFalse = x === null;

Ce qui devient très vite un problème. Le meilleur exemple de la raison pour laquelle la conversion implicite est "diabolique" peut être extrait de ce code dans MFC / C ++ qui sera réellement compilé en raison d'une conversion implicite de CString en HANDLE qui est un type typedef de pointeur ...

CString x;
delete x;

Ce qui, évidemment, pendant l'exécution des choses très indéfinies ...

Google pour les conversions implicites en C ++ et STL pour obtenir certains des arguments contre ...

Thomas Hansen
la source
2
0 == nullc'est faux.
Garrett
21

Comparaison d'égalité:

Opérateur ==

Renvoie vrai, lorsque les deux opérandes sont égaux. Les opérandes sont convertis dans le même type avant d'être comparés.

>>> 1 == 1
true
>>> 1 == 2
false
>>> 1 == '1'
true

Comparaison d'égalité et de type:

Opérateur ===

Renvoie true si les deux opérandes sont égaux et du même type. C'est généralement mieux et plus sûr si vous comparez de cette façon, car il n'y a pas de conversions de type en arrière-plan.

>>> 1 === '1'
false
>>> 1 === 1
true
user2601995
la source
20

Voici un tableau de comparaison pratique qui montre les conversions qui se produisent et les différences entre ==et ===.

Comme l'indique la conclusion:

"Utilisez trois égaux à moins que vous ne compreniez parfaitement les conversions qui ont lieu pour deux égaux."

http://dorey.github.io/JavaScript-Equality-Table/

Christian Hagelid
la source
20

nul et non défini sont le néant, c'est-à-dire

var a;
var b = null;

Ici aet bn'ont pas de valeurs. Alors que 0, false et '' sont toutes des valeurs. Une chose commune entre tous ces éléments est qu'ils sont tous des valeurs de falsification, ce qui signifie qu'ils satisfont tous à des conditions de falsification.

Ainsi, le 0, le faux et le '' forment ensemble un sous-groupe. Et d'autre part, null & undefined forment le deuxième sous-groupe. Vérifiez les comparaisons dans l'image ci-dessous. nul et non défini serait égal. Les trois autres seraient égaux les uns aux autres. Mais, ils sont tous traités comme des conditions de falsification en JavaScript.

Entrez la description de l'image ici

C'est la même chose que n'importe quel objet (comme {}, tableaux, etc.), la chaîne non vide et la valeur booléenne true sont toutes des conditions véridiques. Mais, ils ne sont pas tous égaux.

vivek_nk
la source