Ce qui suit montre que "0"
est faux en Javascript:
>>> "0" == false
true
>>> false == "0"
true
Alors, pourquoi ce qui suit imprime-t-il "ha"
?
>>> if ("0") console.log("ha")
ha
La raison en est que lorsque vous faites explicitement "0" == false
, les deux côtés sont convertis en nombres et , puis la comparaison est effectuée.
Quand vous faites: if ("0") console.log("ha")
, la valeur de la chaîne est en cours de test. Toute chaîne non vide est true
, tandis qu'une chaîne vide est false
.
Egal (==)
Si les deux opérandes ne sont pas du même type , JavaScript les convertit, puis applique une comparaison stricte. Si l'un des opérandes est un nombre ou un booléen , les opérandes sont convertis en nombres si possible; sinon si l'un des opérandes est une chaîne , l'autre opérande est converti en chaîne si possible. Si les deux opérandes sont des objets , JavaScript compare les références internes qui sont égales lorsque les opérandes font référence au même objet en mémoire.
(De opérateurs de comparaison dans Mozilla Developer Network)
Tableaux affichant le problème:
et ==
Morale de l'utilisation de l'histoire ===
crédit de génération de table: https://github.com/dorey/JavaScript-Equality-Table
C'est conforme aux spécifications.
12.5 La déclaration if ..... 2. Si ToBoolean (GetValue (exprRef)) est vrai, alors A. Renvoie le résultat de l'évaluation du premier relevé. 3. Autre, ....
ToBoolean, selon les spécifications, est
L'opération abstraite ToBoolean convertit son argument en une valeur de type Boolean conformément au tableau 11:
Et cette table dit ceci à propos des chaînes:
Le résultat est faux si l'argument est la chaîne vide (sa longueur est égale à zéro); sinon le résultat est vrai
Maintenant, pour expliquer pourquoi "0" == false
, vous devez lire l'opérateur d'égalité, qui indique qu'il tire sa valeur de l'opération abstraite GetValue(lref)
correspond de la même manière pour le côté droit.
Qui décrit cette partie pertinente comme:
si IsPropertyReference (V), alors a. Si HasPrimitiveBase (V) est false, alors get sera la méthode interne [[Get]] de base, sinon, passera get Sera la méthode interne spéciale [[Get]] définie ci-dessous. b. Renvoie le résultat de l'appel de la méthode interne get en utilisant base comme valeur this et en transmettant GetReferencedName (V) à l'argument .
Ou, en d'autres termes, une chaîne a une base primitive, qui rappelle la méthode get interne et finit par paraître fausse.
Si vous souhaitez évaluer des éléments à l'aide de l'opération GetValue, utilisez ==
, si vous souhaitez effectuer une évaluation à l'aide de ToBoolean
, utilisez ===
(également appelé opérateur d'égalité "stricte").
C'est PHP où la chaîne "0"
est falsy (false-when-used-in-boolean-context). En JavaScript, toutes les chaînes non vides sont la vérité.
Le truc, c’est que ==
contre un booléen n’est pas évalué dans un contexte booléen, il est converti en nombre et, dans le cas de chaînes, il est analysé en décimal. Donc vous obtenez Number 0
au lieu de la vérité booléenne true
.
Il s’agit d’un langage vraiment médiocre et c’est l’une des raisons pour lesquelles nous essayons de ne pas utiliser l’opérateur malheureux ==
. Utilisez ===
à la place.
// I usually do this:
x = "0" ;
if (!!+x) console.log('I am true');
else console.log('I am false');
// Essentially converting string to integer and then boolean.
Vos guillemets autour du 0
en font une chaîne qui est évaluée comme étant vraie.
Supprimez les guillemets et cela devrait fonctionner.
if (0) console.log("ha")
Tout cela à cause des spécifications ECMA ... "0" == false
à cause des règles spécifiées ici http://ecma262-5.com/ELS5_HTML.htm#Section_11.9. ... Et if ('0')
est évalué à true en raison des règles spécifiées ici http://ecma262-5.com/ELS5_HTML.htm#Section_12.5
L'expression "if" teste la véracité, alors que la double égalité vérifie l'équivalence indépendante du type. Une chaîne est toujours la vérité, comme d'autres l'ont souligné. Si le double égal vérifiait la véracité de ses deux opérandes, puis comparait les résultats, vous obtiendriez le résultat que vous supposiez intuitivement, à savoir ("0" == true) === true
. Comme le dit Doug Crockford dans son excellent JavaScript: The Good Parts, "les règles selon lesquelles [== contraint les types de ses opérandes] sont compliquées et immémorables .... Le manque de transitivité est alarmant. " Il suffit de dire que l'un des opérandes est forcé à correspondre à l'autre, et que "0" finit par être interprété comme un zéro numérique, ce qui équivaut à faux lorsque forcé à être booléen (ou faux vaut zéro lorsque contraint à un nombre).
== L'opérateur Egalité évalue les arguments après les avoir convertis en nombres. La chaîne zéro "0" est donc convertie en type de données Number et la valeur booléenne false en nombre 0. So
"0" == false // true
La même chose s'applique à
false == "0" //true
=== Le contrôle d'égalité strict évalue les arguments avec le type de données d'origine
"0" === false // false, because "0" is a string and false is boolean
Même chose pour
false === "0" // false
Dans
if("0") console.log("ha");
La chaîne "0" ne compare avec aucun argument, et chaîne est une valeur vraie jusqu'à ou sauf si elle est comparée à un argument. C'est exactement comme
if(true) console.log("ha");
Mais
if (0) console.log("ha"); // empty console line, because 0 is false
`
if (x)
coerces x en utilisant le toBoolean interne à JavaScript (http://es5.github.com/#x9.2)
x == false
contraint les deux parties à l'aide de la contrainte interne toNumber (http://es5.github.com/#x9.3) ou toPrimitive pour les objets (http://es5.github.com/#x9.1)
Pour plus de détails, voir http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/