2011-03-27 27 views
32

He estado leyendo Douglas Crockford's JavaScript: The Good Parts, y me encontré con este ejemplo raro que no tiene sentido para mí:JavaScript igualdad de transitividad es raro

'' == '0'   // false 
0 == ''    // true 
0 == '0'   // true 

false == undefined // false 
false == null  // false 
null == undefined // true 

El autor también se enciende mencionar "nunca utilizar == y !=. En cambio, siempre use === y !== ". Sin embargo, él no explica por qué se exhibe el comportamiento anterior. Entonces mi pregunta es, ¿por qué son los resultados anteriores como son? ¿No se considera transitividad en JavaScript?

+2

La mejor manera de responder a esta pregunta es leer la especificación: http://www.ecma-international.org/publications/standards/Ecma-262.htm Si realmente quiere saber el quid de la cuestión, de por qué las declaraciones anteriores son como son, realmente no hay una mejor manera.Esté preparado de que puede ser un poco difícil en algunos lugares, pero si hace una pregunta como esta, vale la pena el esfuerzo. –

+0

@ T.J. Crowder Muy buena sugerencia (+1), edité ese enlace en mi respuesta, espero que no te importe. – alex

+0

@alex: por supuesto que no. :-) –

Respuesta

25
'' == '0' // false 

El lado izquierdo es un hilo vacío, y el lado derecho es un hilo con un carácter. Son falsos porque está haciendo una comparación entre dos cadenas idénticas (gracias Niall).

0 == '' // true 

Por lo tanto, por lo que éste es verdad, porque es 0Falsy y la cadena vacía es Falsy.

0 == '0' // true 

Esto es un poco más complicado. La especificación establece que si los operandos son una cadena y un número, entonces fuerza la cadena al número. '0' se convierte en 0. Gracias smfoote.

false == undefined // false 

El valor undefined es especial en JavaScript y no es igual a cualquier otra cosa excepto null. Sin embargo, es falsy.

false == null // false 

Nuevamente, null es especial. Solo es igual a undefined. También es falsy.

null == undefined // true 

null y undefined son similares, pero no iguales. null significa nada, mientras que undefined es el valor de una variable no establecida o no existente. Tendría sentido que sus valores se consideren iguales.

Si quieres ser realmente confundido, mira esto ...

'\n\r\t' == 0 

Una cadena que consiste solamente en los espacios en blanco se considera igual a 0.

Douglas Crockford hace que una gran cantidad de recomendaciones, pero no tiene que tomarlos como un evangelio. :)

T.J. Crowder hace una excelente sugerencia de estudiar el ECMAScript Language Specification para conocer toda la historia detrás de estas pruebas de igualdad.

¿Lectura adicional?

The spec.

yolpo (on falsy values)

+2

* "Douglas Crockford hace muchas recomendaciones, pero no tiene que tomarlas como un evangelio". * Bien puesto. Crockford es una persona inteligente que ha pensado mucho en propósito sobre el idioma, por lo que vale la pena leer los argumentos que plantea y los argumentos que hace. Entonces llega a tus propias conclusiones. –

+0

@alex ... en su tercer párrafo que comienza con "Este es un poco más complicado", ¿no quiere decir que '==' no verifica los tipos? – Hristo

+0

@Hristo '==' no comprueba tipos, solo valores. – alex

7

La respuesta a esta pregunta tiene que ver con la forma en JavaScript se encarga de la coacción. En el caso de ==, strings are coerced to be numbers. Por lo tanto:

'' == '0' es equivalente a '' === '0' (ambas son cadenas, por lo que no es necesaria la coacción).

0 == '' es equivalente a 0 === 0 porque la cadena se convierte en el número ''0 (math.abs('') === 0).

0 == '0' es equivalente a 0 === 0 por la misma razón.

false == undefined es equivalente a 0 === undefined porque JavaScript coacciona booleanos sean números cuando los tipos no coinciden

false == null es equivalente a 0 === null por la misma razón.

null == undefined es verdadero porque la especificación lo dice.

Gracias por hacer esta pregunta. Mi comprensión de == es mucho mejor por haberla investigado.

-1

La razón es que la identidad o el operador estricto (===), se compara con ninguna conversión de tipo, es decir, si ambos valores no tienen el mismo valor y el mismo tipo, no se considerarán iguales.

echar un vistazo este enlace, te saca de la duda: easy way to understand how identity operator works

3

en realidad se puede escribir una función de JavaScript que se comporta exactamente igual que == que debe darle una idea de cómo se comporta.

Para mostrar lo que quiero decir aquí es que la función:

// loseEqual() behaves just like `==` 
function loseEqual(x, y) { 
    // notice the function only uses "strict" operators 
    // like `===` and `!==` to do comparisons 

    if(typeof y === typeof x) return y === x; 

    if(typeof y === "function" || typeof x === "function") return false; 

    // treat null and undefined the same 
    var xIsNothing = (y === undefined) || (y === null); 
    var yIsNothing = (x === undefined) || (x === null); 

    if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing); 

    if(typeof x === "object") x = toPrimitive(x); 
    if(typeof y === "object") y = toPrimitive(y); 

    if(typeof y === typeof x) return y === x; 

    // convert x and y into numbers if they are not already use the "+" trick 
    if(typeof x !== "number") x = +x; 
    if(typeof y !== "number") y = +y; 

    return x === y; 
} 

function toPrimitive(obj) { 
    var value = obj.valueOf(); 
    if(obj !== value) return value; 
    return obj.toString(); 
} 

Como se puede ver == tiene una gran cantidad de lógica complicado para la conversión de tipos. Por eso es difícil predecir qué resultado obtendrás.

Éstos son algunos ejemplos de algunos resultados que no esperaba:

verdades inesperadas

[1] == true // returns true 
'0' == false // returns true 
[] == false // returns true 
[[]] == false // returns true 
[0] == false // returns true 

'\r\n\t' == 0 // returns true 

Conclusiones inesperados

// IF an empty string '' is equal to the number zero (0) 
'' == 0 // return true 

// AND the string zero '0' is equal to the number zero (0) 
'0' == 0 // return true 

// THEN an empty string must be equal to the string zero '0' 
'' == '0' // returns **FALSE** 

Objetos con funciones especiales

// Below are examples of objects that 
// implement `valueOf()` and `toString()` 

var objTest = { 
    toString: function() { 
     return "test"; 
    } 
}; 

var obj100 = { 
    valueOf: function() { 
     return 100; 
    } 
}; 

var objTest100 = { 
    toString: function() { 
     return "test"; 
    }, 
    valueOf: function() { 
     return 100; 
    } 
}; 

objTest == "test" // returns true 
obj100 == 100 // returns true 
objTest100 == 100 // returns true 

objTest100 == "test" // returns **FALSE** 
Cuestiones relacionadas