Le développeur JavaScript Douglas Crockford a une fois qualifié les opérateurs javascript ==
et !=
de "jumeaux maléfiques" qui devraient être évités. Cependant, une fois que vous les comprenez, ces opérateurs ne sont pas si mauvais et peuvent réellement être utiles. Cet article explorera ==
et !=
, expliquera comment ils fonctionnent et vous aideront à mieux les comprendre.
Points clés
==
Les opérateurs en JavaScript ne sont pas intrinsèquement mauvais; ils effectuent des moulages de type lors de la comparaison de différents types de valeurs, ce qui est à la fois utile et délicat. !=
===
pour les comparaisons de type direct et de valeur sans moulage, ce qui est plus clair et il est généralement recommandé d'éviter des résultats inattendus. Utilisez !==
et ==
lorsque vous devez lancer ou comparer des valeurs dont les types peuvent changer dynamiquement. !=
==
, afin de prédire les résultats plus précisément et d'éviter les pièges courants. !=
==
exécuter dans divers scénarios, tels que la comparaison des chaînes aux nombres ou des objets aux valeurs d'origine, pour consolider la compréhension. !=
==
ne soient pas effrayants, ils nécessitent une bonne compréhension des règles de distribution de type JavaScrip localement. !=
problématique et ==
opérateurs !=
et ===
, et !==
et ==
. Comprendre pourquoi il existe deux ensembles d'opérateurs d'égalité et dans quelles situations à utiliser quel opérateur a été la source de confusion pour de nombreuses personnes. Les opérateurs !=
et ===
ne sont pas difficiles à comprendre. Lorsque les deux types d'opérande sont les mêmes et que les valeurs sont les mêmes, !==
renvoie ===
et true
renvoie !==
. Cependant, lorsque la valeur ou le type est différent, false
renvoie ===
, false
renvoie !==
. Les opérateurs true
et ==
se comportent de la même manière lorsque les deux types d'opérands sont les mêmes. Cependant, lorsque les types sont différents, JavaScript lance un opérande !=
à un autre type pour rendre l'opérande compatible avant comparaison. Les résultats sont souvent déroutants, comme suit:
"this_is_true" == false // false "this_is_true" == true // false
. Une confusion supplémentaire se produit lorsque vous supposez que la relation de passe (si A est égale à B et B est égal à c) devrait s'appliquer: true
"this_is_true" == false // false "this_is_true" == true // false
Cet exemple montre que ==
manque de transittivité. Si la chaîne vide est égale au nombre 0, et si le nombre 0 est égal à la chaîne composée de caractères 0, la chaîne vide doit être égale à la chaîne composée de 0. Mais ce n'est pas le cas. Lorsqu'un type incompatible est rencontré lors de la comparaison des opérandes via ==
ou !=
, JavaScript lance un type à un autre pour le rendre comparable. Inversement, lors de l'utilisation de ===
et !==
, il n'effectue jamais de moulages de type (ce qui entraîne une légère amélioration des performances). En raison de différents types, ===
renvoie toujours false
dans le deuxième exemple. Comprendre les règles qui contrôlent comment JavaScript jette les opérandes à différents types afin que les deux types d'opérands soient compatibles avant d'appliquer ==
et !=
peut vous aider à déterminer quand il est préférable d'utiliser ==
et !=
, et d'avoir confiance en en utilisant ces opérateurs. Dans la section suivante, nous explorerons les règles de distribution utilisées avec les opérateurs ==
et !=
.
==
et !=
?
et ==
est d'étudier les spécifications du langage ECMAScript. Cette section se concentre sur ECMAScript 262. La section 11.9 de la spécification présente l'opérateur d'égalité. Les opérateurs !=
et ==
apparaissent dans la production de syntaxe !=
et EqualityExpression
. (Contrairement à la première génération, la deuxième génération évite l'opérateur EqualityExpressionNoIn
.) Vérifions la génération in
illustrée ci-dessous. EqualityExpression
'' == 0 // true 0 == '0' // true '' == '0' // false
et ==
, qui ne sont pas liés à cet article.) La section 11.9.1 fournit les informations suivantes sur le fonctionnement de !=
: ===
!==
==
La formule de production
le résultat du calcul
EqualityExpression : EqualityExpression == RelationalExpression
Soit.
Fonctionne:- .
lref
SoitEqualityExpression
être- .
lval
SoitGetValue(lref)
le résultat du calcul- .
rref
SoitRelationalExpression
êtrerval
Renvoie le résultat de la réalisation d'une comparaison d'égalité abstraiteGetValue(rref)
. (Voir 11.9.3.)- La section 11.9.2 fournit des informations similaires sur le fonctionnement
rval == lval
!=
La formule de production
- Soit
lref
le résultat du calculEqualityExpression
.- Soit
lval
êtreGetValue(lref)
.- Soit
rref
le résultat du calculRelationalExpression
.- Soit
rval
êtreGetValue(rref)
.- Soit
r
le résultat de la réalisation de la comparaison de l'égalité abstraiterval != lval
. (Voir 11.9.3.)- Si
r
esttrue
, retournezfalse
. Sinon, retourneztrue
.
lref
et rref
sont des références sur les côtés gauche et droit des opérateurs ==
et !=
. Chaque référence est transmise à la fonction interne GetValue()
pour renvoyer la valeur correspondante. Le noyau de la façon dont ==
et !=
le travail est spécifié par l'algorithme de comparaison d'égalité abstrait, donné dans la section 11.9.3:
Comparez
x == y
, oùx
ety
sont des valeurs, résultant entrue
oufalse
. Cette comparaison est effectuée comme suit:
- si
Type(x)
est le même queType(y)
, alors
- Si
Type(x)
estUndefined
, retourneztrue
.- Si
Type(x)
estNull
, retourneztrue
.- si
Type(x)
estNumber
, alors
- Si
x
estNaN
, retournezfalse
.- Si
y
estNaN
, retournezfalse
.- Si
x
ety
sont la même valeur numérique, renvoyeztrue
.- si
x
est 0 ety
est -0, retourneztrue
.- Si
x
est -0 ety
est 0, alorstrue
sera retourné.- return
false
.- si
Type(x)
estString
, six
ety
sont exactement la même séquence de caractères (la même longueur et les mêmes caractères dans la position correspondante), alorstrue
est renvoyé. Sinon, retournezfalse
.- si
Type(x)
estBoolean
, alors six
ety
sont les deuxtrue
ou sont les deuxfalse
, retourneztrue
. Sinon, retournezfalse
.- Si
x
ety
se référer au même objet, retourneztrue
. Sinon, retournezfalse
.- si
x
estnull
ety
estundefined
, puis retourneztrue
.- si
x
estundefined
ety
estnull
, puis retourneztrue
.- Si
Type(x)
estNumber
etType(y)
estString
, le résultat de la comparaisonx == ToNumber(y)
est renvoyé.- Si
Type(x)
estString
etType(y)
estNumber
, le résultat de la comparaisonToNumber(x) == y
est renvoyé.- Si
Type(x)
estBoolean
, le résultat de la comparaisonToNumber(x) == y
est renvoyé.- Si
Type(y)
estBoolean
, le résultat de la comparaisonx == ToNumber(y)
est renvoyé.- Si
Type(x)
estString
ouNumber
etType(y)
estObject
, le résultat de la comparaisonx == ToPrimitive(y)
est renvoyé.- Si
Type(x)
estObject
etType(y)
estString
ouNumber
, le résultat de la comparaisonToPrimitive(x) == y
est renvoyé.- return
false
.
Étape 1 Le type d'opérande est le même lorsqu'il est exécuté dans cet algorithme. Il montre que undefined
est égal à undefined
, et null
est égal à null
.Il montre également que rien égal à NaN
(non-nombre), deux valeurs identiques sont égales, 0 est égal à -0, deux chaînes avec la même longueur et la même séquence de caractères sont égales, true
égaux true
, false
est égal à false
, et deux références au même objet sont égales. Les étapes 2 et 3 montrent pourquoi null != undefined
renvoie false
. JavaScript considère que ces valeurs sont les mêmes. À partir de l'étape 4, l'algorithme devient intéressant. Cette étape se concentre sur l'égalité entre les valeurs Number
et String
. Lorsque le premier opérande est Number
et que le deuxième opérande est String
, le deuxième opérande est converti en ToNumber()
via la fonction interne de Number
. L'expression x == ToNumber(y)
signifie la récursivité; l'algorithme à partir de la section 11.9.1 est réappliqué. L'étape 5 est équivalente à l'étape 4, mais le premier opérande a un type String
et doit être converti en type Number
. Les étapes 6 et 7 convertissent l'opérande booléen en un type Number
et récursivement. Si l'autre opérande est un booléen, il sera converti en Number
la prochaine fois que cet algorithme sera exécuté, ce qui reviendra à nouveau. D'un point de vue de performance, vous pouvez vous assurer que les deux opérandes sont des types booléens pour éviter deux étapes récursives. L'étape 9 montre que si le type d'opérande est Object
, l'opérande est converti en valeur d'origine via la fonction interne ToPrimitive()
et l'algorithme récursivement. Enfin, l'algorithme considère que les deux opérandes ne sont pas égaux et renvoient false
à l'étape 10. Bien que détaillée, l'algorithme de comparaison d'égalité abstrait est assez facile à comprendre. Cependant, il fait référence à une paire de fonctions internes ToNumber()
et ToPrimitive()
, dont le travail interne doit être exposé pour bien comprendre l'algorithme. La fonction ToNumber()
convertit ses paramètres en Number
et est décrite dans la section 9.3. La liste suivante résume les paramètres non nucères possibles et les valeurs de retour équivalentes:
Undefined
, retournez NaN
. Null
, retournez 0. true
, retournez 1. Si le paramètre est une valeur booléenne false
, retournez 0. Number
, le paramètre d'entrée est renvoyé - pas de conversion. String
, alors la section 9.3.1 «Tonumber du type de chaîne» est appliquée. Renvoie la valeur correspondant au paramètre de chaîne indiqué par la syntaxe. Si le paramètre ne correspond pas à la syntaxe indiquée, retournez NaN
. Par exemple, le paramètre "xyz" provoque le retour NaN
. De plus, le paramètre "29" entraîne un retour de 29. Object
, appliquez les étapes suivantes: primValue
être ToPrimitive(输入参数, 提示Number)
. ToNumber(primValue)
. ToPrimitive()
accepte un paramètre d'entrée et un paramètre facultatif PreferredType
. Les paramètres d'entrée sont convertis en type non objet. Si l'objet peut être converti en plusieurs types primitifs, ToPrimitive()
utilisez l'invite PreferredType
facultative pour biaiser le type préféré. La conversion est effectuée comme suit:
Undefined
, le paramètre d'entrée (Undefined
) est renvoyé - pas de conversion. Null
, le paramètre d'entrée (Null
) est renvoyé - pas de conversion. Boolean
, renvoyez le paramètre d'entrée - pas de conversion. Number
, renvoyez le paramètre d'entrée - pas de conversion. String
, renvoyez le paramètre d'entrée - pas de conversion. Object
, la valeur par défaut correspondant au paramètre d'entrée est renvoyée. Récupérez la valeur par défaut de l'objet en appelant la méthode interne de l'objet [[DefaultValue]]
et en passant une invite PreferredType
facultative. Le comportement de [[DefaultValue]]
est défini dans la section 8.12.8 pour tous les objets ECMascript natifs. Cette section présente pas mal de théories. Dans la section suivante, nous nous tournerons en pratiquant en fournissant diverses expressions impliquant ==
et !=
et en effectuant progressivement des étapes algorithmiques.
comprendre les jumeaux maléfiques
Maintenant que nous avons compris comment ==
et !=
fonctionnent selon les spécifications ECMAScript, profitons de ces connaissances en explorant les différentes expressions impliquant ces opérateurs. Nous allons expliquer comment évaluer ces expressions et découvrir pourquoi ils sont true
ou false
. Pour mon premier exemple, considérons les paires d'expression suivantes introduites vers le début de l'article:
"this_is_true" == false // false "this_is_true" == true // false
Suivez l'algorithme de comparaison d'égalité abstrait pour évaluer ces expressions selon les étapes suivantes:
typeof "this_is_true"
Renvoie "String", tandis que typeof false
ou typeof true
Renvoie "booléen". Boolean
. L'expression est convertie en "this_is_true" == ToNumber(false)
et "this_is_true" == ToNumber(true)
. ToNumber(false)
Renvoie 0, ToNumber(true)
Renvoie 1, qui simplifie les expressions à "this_is_true" == 0
et "this_is_true" == 1
respectivement. À cette époque, l'algorithme récursivement. String
et le type de l'opérande droit est Number
. L'expression est convertie en ToNumber("this_is_true") == 0
et ToNumber("this_is_true") == 1
. ToNumber("this_is_true")
Renvoie NaN
, ce qui simplifie les expressions à NaN == 0
et NaN == 1
respectivement. À cette époque, l'algorithme récursivement. NaN
, 0 et 1 sont tous Number
. Évitez les étapes 1.A et 1.B qui ne sont pas applicables. Cependant, l'étape 1.C.I s'applique car l'opérande gauche est NaN
. L'algorithme renvoie désormais false
(NaN
n'est égal à rien, y compris lui-même) car la valeur de chaque expression d'origine et recouvrent la pile pour quitter la récursivité complètement. Mon deuxième exemple (basé sur l'explication de la signification de la vie dans le "Galaxy Wandering Guide") compare un objet avec un nombre de ==
et renvoie true
:
"this_is_true" == false // false "this_is_true" == true // false
Les étapes suivantes montrent comment JavaScript utilise l'algorithme de comparaison d'égalité abstrait pour obtenir true
comme valeur de l'expression:
Object
et le type de l'opérande droit est Number
. L'expression est convertie en ToPrimitive(lifeAnswer) == 42
. ToPrimitive()
Appelez la méthode interne lifeAnswer
de [[DefaultValue]]
, sans invite. Selon la section 8.12.8 de la spécification ECMAScript 262, le [[DefaultValue]]
appelle la méthode toString()
, qui renvoie "42". L'expression est convertie en "42" == 42
, et l'algorithme est récursif. String
et le type de l'opérande droit est Number
. L'expression est convertie en ToNumber("42") == 42
. ToNumber("42")
Renvoie 42, et l'expression est convertie en 42 == 42
. L'algorithme recurse et exécute l'étape 1.C.III. Parce que les nombres sont les mêmes, true
est retourné et élargi récursivement. Pour mon dernier exemple, découvrons pourquoi la séquence suivante ne montre pas la transitivité, où la troisième comparaison reviendra true
au lieu de false
:
"this_is_true" == false // false "this_is_true" == true // false
Les étapes suivantes montrent comment JavaScript utilise l'algorithme de comparaison d'égalité abstrait pour obtenir true
comme valeur de '' == 0
.
ToNumber('') == 0
, qui est converti en 0 == 0
, et l'algorithme récursivement. (La section 9.3.1 de la spécification indique que StringNumericLiteral ::: [vide] MV [Valeur mathématique] est 0. En d'autres termes, la valeur d'une chaîne vide est 0.) true
(et élargit la récursivité). Les étapes suivantes montrent comment JavaScript utilise l'algorithme de comparaison d'égalité abstrait pour obtenir true
comme valeur de 0 == '0'
:
0 == ToNumber('0')
, qui est converti en 0 == 0
, et l'algorithme récursivement. true
(et élargit la récursivité). Enfin, JavaScript effectue l'étape 1.D dans l'algorithme de comparaison d'égalité abstrait pour obtenir true
comme valeur de '' == '0'
. Parce que les deux chaînes ont des longueurs différentes (0 et 1), retournez false
.
Conclusion
Vous vous demandez peut-être pourquoi vous devriez prendre la peine d'utiliser ==
et !=
. Après tout, des exemples précédents ont montré que ces opérateurs peuvent être plus lents que les opérateurs ===
et !==
en raison de la coulée et de la récursivité de type. Vous voudrez peut-être utiliser ==
et !=
car dans certains cas, il n'y a aucun avantage. Considérez l'exemple suivant: ===
"this_is_true" == false // false "this_is_true" == true // false
typeof
renvoie une valeur String
. Étant donné que la valeur String
est comparée à une autre valeur String
("objet"), aucune coulée de type ne se produit, et ==
est aussi efficace que ===
. Peut-être qu'un débutant JavaScript qui n'a jamais rencontré ===
trouvera un tel code plus clair. De même, l'extrait de code suivant ne nécessite pas de coulée de type (les types des deux opérandes sont Number
), donc !=
est aussi efficace que !==
:
'' == 0 // true 0 == '0' // true '' == '0' // false
Ces exemples montrent que ==
et !=
conviennent aux comparaisons qui ne nécessitent pas de coulée. Lorsque les types d'opérands sont différents, ===
et !==
sont les meilleurs choix car ils retournent false
plutôt que des valeurs inattendues (par exemple false == ""
renvoie true
). Si le type d'opérande est le même, il n'y a aucune raison de ne pas utiliser ==
et !=
. Il est peut-être temps d'arrêter d'avoir peur des jumeaux diaboliques, et une fois que vous les comprenez, ils sont moins mauvais.
FAQS pour les opérateurs de l'égalité et de comparaison JavaScript (FAQ)
Quelle est la différence entre==
et ===
dans JavaScript? en javascript, ==
et ===
sont des opérateurs de comparaison. Cependant, ils diffèrent dans la façon dont ils comparent les valeurs. L'opérateur ==
(également connu sous le nom de l'opérateur d'égalité lâche) effectue une coulée de type avant la comparaison. Cela signifie que si vous comparez deux types de valeurs différents, JavaScript essaiera de convertir un type en un autre avant d'effectuer la comparaison. D'un autre côté, l'opérateur ===
(appelé l'opérateur d'égalité strict) n'effectue pas de coulée de type. Il compare les valeurs et les types en même temps, ce qui signifie que si les deux types de valeurs sont différents, JavaScript les considérera comme inégaux.
===
au lieu de ==
en javascript? est généralement recommandé d'utiliser ===
au lieu de ==
dans JavaScript, car il fournit des comparaisons plus strictes, ce qui signifie qu'il n'effectue pas de fonds de type et vérifie les valeurs et les types. Cela peut aider à éviter des résultats inattendus lors de la comparaison de différents types de valeurs. Par exemple, lors de l'utilisation de ==
, JavaScript considère le nombre 0 et la chaîne vide "" égale, car il convertit le type avant la comparaison. Cependant, en utilisant ===
, ils seront considérés comme inégaux car ils sont de types différents.
Le type coulé dans JavaScript fait référence à la conversion automatique ou implicitement des valeurs d'un type de données en un autre. Cela se produit lorsque les opérateurs sont utilisés pour différents types d'opérands ou lorsqu'il est nécessaire d'un certain type. Par exemple, lors de l'utilisation de l'opérateur d'égalité lâche (==
), JavaScript essaiera de convertir les opérandes en types généraux avant de faire des comparaisons.
Dans JavaScript, les objets sont comparés par référence, et non par valeur. Cela signifie que même si deux objets ont exactement les mêmes propriétés et valeurs, elles ne sont pas considérées comme égales car elles se réfèrent à différents objets en mémoire. Le seul cas où les objets sont considérés comme égaux est qu'ils se réfèrent exactement au même objet.
Quelle est la différence entre==
et !=
dans JavaScript? ==
et !=
sont des opérateurs de comparaison en JavaScript. L'opérateur ==
vérifie si les valeurs des deux opérandes sont égales et effectue des lancers si nécessaire. D'un autre côté, l'opérateur !=
vérifie si les valeurs des deux opérandes ne sont pas égales et effectue des lancers de type si nécessaire.
===
et !==
dans JavaScript? ===
et !==
sont des opérateurs de comparaison en JavaScript. L'opérateur ===
vérifie si les valeurs des deux opérandes sont égales, en tenant compte des valeurs et des types. En revanche, l'opérateur !==
vérifie si les valeurs des deux opérandes ne sont pas égales, en tenant compte des valeurs et des types.
Dans JavaScript, les tableaux sont des objets, par rapport à la référence, et non par valeur. Cela signifie que même si deux tableaux contiennent les mêmes éléments dans le même ordre, ils ne sont pas considérés comme égaux car ils se réfèrent à différents objets en mémoire. Pour comparer deux tableaux par leur contenu, vous devez comparer chaque élément séparément.
null
et undefined
? dans JavaScript, null
et undefined
sont considérés comme vaguement égaux (==
) car ils représentent tous les deux des valeurs manquantes. Cependant, ils ne sont pas strictement égaux (===
) car ils sont de types différents.
En JavaScript, les opérateurs de comparaison ont le même niveau de priorité. Ils sont calculés de gauche à droite. Cependant, il est important de noter qu'ils ont une priorité inférieure à celle des opérateurs arithmétiques et bit, mais plus élevés que les opérateurs logiques.
Oui, vous pouvez utiliser des opérateurs de comparaison avec des chaînes en JavaScript. JavaScript utilise l'ordre lexical (dictionnaire) lors de la comparaison des chaînes. Cependant, il est important de noter que les lettres majuscules sont considérées comme "petites" que les lettres minuscules car elles ont des valeurs ASCII plus petites.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!