11
votes

Conversion de type de données implicite dans JavaScript lorsque vous comparez entier avec chaîne en utilisant ==

Le code: xxx

La question:

  1. en programmation C Nous avons un nom de règle Type de données Promotion, où lorsqu'il y a un mélange de type de données (exemple: ajout de point entier et flottant), l'entier sera d'abord converti en un point flottant avant que l'addition soit effectuer.

  2. Le code ci-dessus me demandera une boîte d'alerte avec le message "ÇA Fonctionne" indique que la condition de test est évaluée à true.

  3. Pour JavaScript dactylographié de manière lâche, je suis juste curieux: y a-t-il une règle comme c qui détermine la conversion effectuera dans quelle situation? En plus de cela, le code JavaScript ci-dessus convertit la valeur de la variable à partir d'une valeur entière à la valeur de chaîne avant de comparer ou inversement?


2 commentaires

J'ai du mal à essayer de passer de la programmation C Retour à JavaScript ou à PHP car certains sont différents dans certaines règles, c'est comme si mon cerveau est utilisé aux règles de C et quand j'essaie de coder en JavaScript, mon cerveau continuera à penser aux règles C


Pour le point 1, dans JavaScript, tous les numéros sont un point flottant, de sorte que int à float Les promotions ne sont pas nécessaires.


5 Réponses :


6
votes

En JavaScript, il existe deux opérateurs pouvant être utilisés pour comparer deux valeurs: le == et === opérateurs.

cité de JavaScript dans le guide définitif 6ème édition:

L'opérateur d'égalité == est comme l'opérateur d'égalité strict ( === ), mais il est moins strict. Si les valeurs des deux opérandes ne sont pas du même type, Il tente de faire des conversions de type et essaie à nouveau la comparaison.

et

L'opérateur d'égalité strict === évalue ses opérandes, puis compare la deux valeurs comme suit, n'effectuons aucune conversion de type.

Donc, je vous suggère d'utiliser === tout le temps pour éviter des problèmes tels que: xxx


1 commentaires

Douglas Crockford convient avec vous: "Mon conseil est de ne jamais utiliser les jumeaux diaboliques. Au lieu de cela, utilisez toujours === et ! == ." (Voir Stackoverflow.com/a/359509/3779853 ). J'aime cette approche, mais que dois-je faire si je veux "1" et 1 à considérer égal quelque part dans mon code, par exemple après une importation JSON? parseint ?



21
votes

Oui, toutes les règles de la conversion de type appliquée par l'opérateur Equals sont décrites sur la spécification ECMA-262, dans L'égalité abstraite Algorithme de comparaison .

L'algorithme peut sembler assez complexe, mais on peut résumer les cas suivants:

  1. Le type Les deux opérandes sont les mêmes:

    • pour les primitives (chaîne, nombre, booléen, null, indéfini)
      • retourne vrai si la valeur est exactement la même
      • pour le type d'objet
        • retourne vrai si les deux références indiquent le même objet
        • si les types des deux opérandes diffèrent

          • Si le type d'un opérande est nul ou indéfini
            • retourne vrai uniquement si l'autre valeur de l'opérande est soit null ou non défini
            • Si l'un des opérandes est de type booléen ou numéro
              • (après quelques étapes) Convertissez l'autre opérande en numéro et comparez
              • Si l'un des opérandes est un objet et l'autre est une primitive

                • Effectuez une conversion d'objet à primitive sur l'objet et comparez à nouveau

                  La conversion d'objet à primitive est effectuée via une opération abstraite appelée toprimitive , cette méthode essaiera de convertir l'objet en une valeur primitive, à l'aide de l'interne [[primiitiveValue]] méthode.

                  Ceci essaiera d'éjecter la valeur de l'objetOf et TOSTRING méthodes, et il prendra la valeur du premier qui revient une valeur primitive.

                  Dans le cas, ces deux méthodes ne renvoient pas une primitive, sinon elles ne sont pas appelables, un TypeError est lancé, par exemple: < Pré> xxx

                  La déclaration ci-dessus produira un typeError car l'objet par défaut.pototype.valueof ne fait rien de plus que le même instance d'objet ( ceci , pas une valeur primitive) et nous définissons une propriété Tostring non une fonction non une fonction.

                  Un ami a fait un petit outil pourrait être int eurtifie à vous, il montre toutes les étapes et toutes les comparaisons récursives entre types:


0 commentaires

3
votes

Évitez la conversion de type implicite dans JavaScript. Prenez toujours des mesures pour tester et / ou convertir des valeurs individuelles avant de les comparer pour que vous comparez des pommes aux pommes. Testez toujours explicitement pour indéfini pour déterminer si une valeur ou une propriété a une valeur, utilisez NULL pour indiquer que les variables ou les propriétés d'objet ne font référence à aucun objet, et convertissent et comparent toutes les autres valeurs pour que les opérations sont effectuées contre les valeurs du même type. .


0 commentaires

0
votes

Je sais que la question a été répondue. Ce que j'ai donné ci-dessous est un exemple de quelques conversions. Ce sera utile pour quelqu'un qui est nouveau à JavaScript. La sortie ci-dessous peut être comparée à l'algorithme général pour une compréhension facile.

Le code: p> xxx pré>

la sortie: p>

"Start"
"123"
" Number(x) = 123"
" parseInt(x, 10) = 123"
" parseFloat(x) = 123"
" +x = 123"
" !!x = true"
"End"

"Start"
undefined
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = false"
"End"

"Start"
"not a number"
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = true"
"End"

"Start"
"123.45"
" Number(x) = 123.45"
" parseInt(x, 10) = 123"
" parseFloat(x) = 123.45"
" +x = 123.45"
" !!x = true"
"End"

"Start"
"1234 error"
" Number(x) = NaN"
" parseInt(x, 10) = 1234"
" parseFloat(x) = 1234"
" +x = NaN"
" !!x = true"
"End"

"Start"
""
" Number(x) = 0"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 0"
" !!x = false"
"End"

"Start"
"       "
" Number(x) = 0"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 0"
" !!x = true"
"End"

"Start"
null
" Number(x) = 0"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 0"
" !!x = false"
"End"

"Start"
undefined
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = false"
"End"

"Start"
true
" Number(x) = 1"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 1"
" !!x = true"
"End"

"Start"
false
" Number(x) = 0"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 0"
" !!x = false"
"End"

"Start"
"true"
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = true"
"End"

"Start"
"false"
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = true"
"End"


0 commentaires

0
votes

Mieux utiliser ci-dessous Code pour la compréhension de la conversion implicite.

p>

var values = [ 0 , 123, "0", "123", -0, +0, NaN, +NaN, -NaN, false, true, "false", "true", null, undefined, "null", "undefined", "", "GoodString", "  "];

for (var i = 0; i < values.length; i++){
    console.log("<<<<<<<<<<<<Starting comparing:  " + i + ">>>>>>>>>>>>>>>");
    for (var j = 0; j < values.length; j++){
		console.log(values[i],`==`, values[j]);
		console.log(eval(values[i] == values[j]));
	}
}


0 commentaires