web-dev-qa-db-fra.com

En JavaScript, pourquoi "0" est-il égal à false, mais lorsqu'il est testé par "if", il n'est pas faux en soi?

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
218

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)

240
jdi

Tableaux affichant le problème:

truthy if statement

et == truthy comparisons of all object types in javascript

Morale de l'utilisation de l'histoire === strict equality displaying sanity

crédit de génération de table: https://github.com/dorey/JavaScript-Equality-Table

329
Joe

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:

enter image description here

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").

36
Incognito

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.

12
bobince
// 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.
7
Thava

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") 
4
Jason Gennaro

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

2
Narendra Yadala

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).

1
Jollymorphic

== 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

`

1
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/

0
AngusC