2010-05-26 18 views
104

Tuve que escribir una rutina que incrementa el valor de una variable en 1 si su tipo es number y asigna 0 a la variable de no ser así, donde la variable es inicialmente null o undefined.¿Por qué `null> = 0 && null <= 0` pero no` null == 0`?

La primera implementación fue v >= 0 ? v += 1 : v = 0 porque pensé que cualquier cosa que no fuera un número haría que una expresión aritmética fuera falsa, pero estaba mal, ya que null >= 0 se evalúa como verdadero. Entonces aprendí que null se comporta como 0 y las siguientes expresiones se evalúan como verdaderas.

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

Por supuesto, null no es 0. null == 0 se evalúa a falso. Esto hace que la expresión aparentemente tautológica (v >= 0 && v <= 0) === (v == 0) sea falsa.

¿Por qué null tiene 0, aunque en realidad no es 0?

+3

Él está hablando de Javascript. Tu ejemplo está en PHP. En PHP, el operador == compara los valores de una manera especial. Puedes hacer algunas comparaciones realmente locas como "10" == "1e1" (que es verdad). Si utilizó el operador ===, obtendría un resultado completamente diferente porque verifica si el tipo coincide con el valor. Verifique este enlace: http://www.php.net/manual/en/language.operators.comparison.php – Pijusn

+0

El operador PHP '==' realmente funciona de una manera "especial". –

+0

Si su requisito era comenzar a contar en 1 en lugar de 0, hay una manera muy lata de incrementar los contadores que son inicialmente 'null' o' undefined': 'c = - ~ c // Resultados en 1 para null/undefined; incrementos si ya existe un número ' –

Respuesta

160

Su verdadera pregunta parece ser:

qué:

null >= 0; // true 

Pero:

null == 0; // false 

Lo que realmente sucede es que el Mayor que o igual operador (>=), realiza coerción de tipo (ToPrimitive), con sugerencia tipo de Number, en realidad todos los operadores relacionales tienen este comportamiento.

null es tratado de una manera especial por el operador de igualdad (==). En un breve, sólo coacciona a undefined:

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

Valor como false, '', '0' y [] están sujetos a la coerción de tipo numérico, todos ellos coaccionar a cero.

Puede ver los detalles internos de este proceso en The Abstract Equality Comparison Algorithm y The Abstract Relational Comparison Algorithm.

En resumen:

  • Relational Comparación: si los dos valores no son tipo de cadena, ToNumber se llama en ambos. Esto es lo mismo que agregar un + al frente, que para las coerces nulas al 0.

  • Igualdad de comparación: solo llama a ToNumber en cadenas, números y booleanos.

+1

Hola CMS, según tu explicación la primitiva nula es 0, entonces 0> = 0 devuelve verdadero y == devuelve falso.pero según el algoritmo ecma Si Tipo (x) es Objeto y Tipo (y) es Cadena o Número , devuelve el resultado de la comparación ToPrimitive (x) == y.then en esto debe devolver true.please me explique –

+0

para mí la respuesta no proporciona una * respuesta * - 'null es tratada de manera especial por el Equal Operator (==). En un resumen, solo coacciona a indefinido: '¿y qué? ¿Puedes explicar por qué 'null> = 0'? :) –

+0

@bharathmuppa @ Andrey-Deineko: El resto de la respuesta de la CMS está aquí: [El resumen relacional Comparación Algoritmo] (http://www.ecma-international.org/ecma-262/5.1/#sec -11.8.5) que explica en el punto 3. que si ambos valores no son de tipo String, se llama a ToNumber en ambos. Esto es lo mismo que agregar un '+' al frente, que para las coerces nulas a '0'. Igualdad solo llama a ToNumber en cadenas, números y booleanos. –

7

Me gustaría extender la cuestión de mejorar aún más la visibilidad del problema:

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

Simplemente no tiene sentido. Al igual que los idiomas humanos, estas cosas deben aprenderse de memoria.

0

¡Tuve el mismo problema! Actualmente mi única solución es separarme.

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 ambas comparaciones estrictas y el tipo de conversión de la

null >= 0; es cierto pero (null==0)||(null>0) es falso

null <= 0; es cierto, pero (null==0)||(null<0) es falso

"" >= 0 también es cierto

Para comparaciones abstractas relacionales (< =,> =), los operandos primero se convierten en primitivos, y luego en el mismo tipo, antes de la comparación.

typeof null returns "object"

Cuando el tipo es objeto javascript intenta stringify el objeto (es decir, null) los pasos siguientes se toman (ECMAScript 2015):

  1. Si PreferredType no fue aprobada, deja hint ser "default ".
  2. Else if PreferredType es hint Cadena, deje hint ser "cadena".
  3. Else PreferredType es hint Número, deje hint ser "number".
  4. Deje exoticToPrim ser GetMethod(input, @@toPrimitive).
  5. ReturnIfAbrupt(exoticToPrim).
  6. Si exoticToPrim no está indefinido, entonces
    a) Deje que el resultado sea Call(exoticToPrim, input, «hint»).
    b) ReturnIfAbrupt(result).
    c) Si Type(result) no es Object, devuelve el resultado.
    d) Lanza una excepción TypeError.
  7. Si hint es "predeterminado", deje hint ser "número".
  8. Devuelve OrdinaryToPrimitive(input,hint).

Los valores permitidos para la sugerencia son "predeterminado", "número" y "cadena". Los objetos de fecha son únicos entre los objetos integrados de ECMAScript porque tratan "por defecto" como el equivalente a "cadena". Todos los demás objetos incorporados de ECMAScript tratan "por defecto" como el equivalente a "número". (ECMAScript 20.3.4.45)

Así que creo null convierte a 0.