2010-05-26 8 views
104

J'ai dû écrire une routine qui incrémente la valeur d'une variable de 1 si son type est number et affecte 0 à la variable sinon, où la variable est initialement null ou undefined.Pourquoi `null> = 0 && null <= 0` mais pas` null == 0`?

La première implémentation était v >= 0 ? v += 1 : v = 0 car je pensais que tout ce qui n'était pas un nombre rendrait une expression arithmétique fausse, mais elle était erronée puisque null >= 0 est évalué à vrai. Puis j'ai appris null se comporte comme 0 et les expressions suivantes sont toutes évaluées à vrai.

  • null >= 0 && null <= 0
  • !(null < 0 || null > 0)
  • null + 1 === 1
  • 1/null === Infinity
  • Math.pow(42, null) === 1

Bien sûr, null n'est pas 0. null == 0 est évaluée à false. Cela rend l'expression apparemment tautologique (v >= 0 && v <= 0) === (v == 0) fausse.

Pourquoi est null comme 0, bien qu'il ne soit pas réellement 0?

+3

Il parle de Javascript. Votre exemple est en PHP. Dans l'opérateur PHP == compare les valeurs d'une manière spéciale. Vous pouvez faire des comparaisons vraiment folles comme "10" == "1e1" (ce qui est vrai). Si vous avez utilisé l'opérateur ===, vous obtiendrez un résultat totalement différent car il vérifie si le type correspond à la valeur. Consultez ce lien: http://www.php.net/manual/fr/language.operators.comparison.php – Pijusn

+0

L'opérateur PHP '==' fonctionne vraiment de manière "spéciale". –

+0

Si votre exigence était de commencer à compter à 1 au lieu de 0, il y a une façon vraiment concise d'incrémenter les compteurs qui sont initialement 'null' ou 'undefined':' c = - ~ c // Résultats en 1 pour null/undefined; incrémente si déjà un nombre –

Répondre

160

Votre vraie question semble être:

Pourquoi:

null >= 0; // true 

Mais:

null == 0; // false 

Qu'est-ce qui se passe réellement est que le Grand-que ou égal opérateur (>=), effectue une coercition de type (ToPrimitive), avec un indice type de Number, en réalité tous les opérateurs relationnels ont ce comportement.

null est traité d'une manière spéciale par le opérateur égal (==). Dans un bref, il ne -undefined contraint:

null == null; // true 
null == undefined; // true 

valeur telle que false, '', '0' et [] sont soumis à la contrainte de type numérique, tous les contraindre à zéro.

Vous pouvez voir les détails intérieurs de ce processus dans The Abstract Equality Comparison Algorithm et The Abstract Relational Comparison Algorithm.

En résumé:

  • Comparaison Relationnel: si les deux valeurs ne sont pas de type String, ToNumber est appelé à la fois. C'est la même chose que d'ajouter un + à l'avant, ce qui est nul pour 0.

  • Comparaison d'égalité: appelle uniquement ToNumber sur les chaînes, les nombres et les booléens.

+1

Salut CMS, selon votre explication, la primitive NULL est 0, alors 0> = 0 renvoie true et == renvoie false. Mais selon l'algorithme ecma Si Type (x) est Object et Type (y) est String ou Number , renvoyer le résultat de la comparaison ToPrimitive (x) == y.En ce cas, il devrait renvoyer true.please m'expliquer –

+0

pour moi la réponse ne fournit pas une * réponse * - 'null est traité d'une manière spéciale par le Egal à l'opérateur (==). En un mot, cela ne fait que confirmer: "- et quoi? Pouvez-vous expliquer, pourquoi 'null> = 0'? :) –

+0

@bharathmuppa @ andrey-Deineko: Le reste de la réponse de la CMS est ici: [The Abstract Comparaison Relational algorithme] (http://www.ecma-international.org/ecma-262/5.1/#sec -11.8.5) qui explique au point 3. que si les deux valeurs ne sont pas de type String, ToNumber est appelé sur les deux. C'est la même chose que d'ajouter un '+ 'devant, qui vaut null pour' 0'. L'égalité n'appelle que ToNumber sur les chaînes, les nombres et les booléens. –

7

Je voudrais étendre la question afin d'améliorer la visibilité du problème:

null >= 0; //true 
null <= 0; //true 
null == 0; //false 
null > 0; //false 
null < 0; //false 

Cela n'a aucun sens. Comme les langues humaines, ces choses doivent être apprises par cœur.

0

J'ai eu le même problème !! Actuellement, ma seule solution est de séparer.

var a = null; 
var b = undefined; 

if (a===0||a>0){ } //return false !work! 
if (b===0||b>0){ } //return false !work! 

//but 
if (a>=0){ } //return true ! 
3

JavaScript a des comparaisons strictes et de conversion de type

null >= 0; est vrai mais (null==0)||(null>0) est faux

null <= 0; est vrai, mais (null==0)||(null<0) est faux

"" >= 0 est également vrai

Pour les comparaisons abstraites relationnelles (< =,> =), les opérandes sont d'abord converties en primitives, puis au même type, avant comparaison.

typeof null returns "object"

Lorsque le type est objet javascript tente de stringify l'objet (par exemple null) les étapes suivantes sont prises (ECMAScript 2015): n'a pas été adopté

  1. Si PreferredType, laissez hint être « par défaut ".
  2. Sinon, PreferredType est hint Chaîne, laissez hint être "chaîne".
  3. Sinon PreferredType est hint Nombre, soit hint être "nombre".
  4. Soit exoticToPrim soit GetMethod(input, @@toPrimitive).
  5. ReturnIfAbrupt(exoticToPrim).
  6. Si exoticToPrim n'est pas indéfini, alors
    a) Soit le résultat Call(exoticToPrim, input, «hint»).
    b) ReturnIfAbrupt(result).
    c) Si Type(result) n'est pas un objet, retournez le résultat.
    d) Lève une exception TypeError.
  7. Si hint est "par défaut", laissez hint être "numéro".
  8. Renvoyer OrdinaryToPrimitive(input,hint).

Les valeurs autorisées pour l'indicateur sont "default", "number" et "string". Les objets de date sont uniques parmi les objets ECMAScript intégrés car ils traitent "default" comme étant équivalent à "string". Tous les autres objets ECMAScript intégrés traitent "default" comme étant équivalent à "number". (ECMAScript 20.3.4.45)

Je pense donc que null convertit à 0.

Questions connexes