tag - JavaScript transitivity igualdad es raro
title of page html (4)
He estado leyendo el JavaScript de Douglas Crockford : The Good Parts , y me encontré con este extraño ejemplo que no tiene sentido para mí:
'''' == ''0'' // false
0 == '''' // true
0 == ''0'' // true
false == undefined // false
false == null // false
null == undefined // true
El autor también menciona "nunca usar ==
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?
En realidad, puede escribir una función de JavaScript que se comporte exactamente igual que ==
que debería proporcionarle una idea de cómo se comporta.
Para mostrarte lo que quiero decir aquí está esa 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 puede ver, ==
tiene mucha lógica complicada para la conversión de tipos. Por eso es difícil predecir qué resultado obtendrás.
Estos son algunos ejemplos de algunos resultados que no esperarías:
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 inesperadas
// 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**
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.
eche un vistazo a este enlace, lo saca de dudas: forma fácil de entender cómo funciona el operador de identidades
La respuesta a esta pregunta tiene que ver con cómo JavaScript maneja la coerción. En el caso de ==
, las cadenas se fuerzan para ser números . Por lo tanto:
'''' == ''0''
es equivalente a '''' === ''0''
(ambos son cadenas, por lo que no es necesaria la coacción).
0 == ''''
es equivalente a 0 === 0
porque la cadena ''''
convierte en el número 0
( math.abs('''') === 0
).
0 == ''0''
es equivalente a 0 === 0
por la misma razón.
false == undefined
equivale a 0 === undefined
porque JavaScript fuerza a los booleanos a ser 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 así lo dice.
Gracias por hacer esta pregunta. Mi comprensión de ==
es mucho mejor por haberlo investigado.
'''' == ''0'' // false
El lado izquierdo es una cadena vacía, y el lado derecho es una cadena con un caracter. Son falsos porque está haciendo una comparación entre dos cadenas idénticas (gracias Niall ).
0 == '''' // true
Por lo tanto, por qué este es verdadero, porque 0
es falso y la cadena vacía es falso .
0 == ''0'' // true
Este 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''
convierte en 0
. Gracias smfoote .
false == undefined // false
El valor undefined
es especial en JavaScript y no es igual a nada más que null
. Sin embargo, es falso .
false == null // false
Nuevamente, null
es especial. Solo es igual a undefined
. También es falso .
null == undefined // true
null
e undefined
son similares, pero no son lo mismo. null
no significa nada , mientras que undefined
es el valor para una variable no establecida o no existente. Tendría sentido que sus valores se consideren iguales.
Si quieres estar realmente confundido, mira esto ...
''/n/r/t'' == 0
Una cadena que consta únicamente de espacios en blanco se considera igual a 0.
Douglas Crockford hace muchas recomendaciones, pero no tiene que tomarlas como un evangelio. :)
TJ Crowder hace una excelente sugerencia de estudiar la ecma-international.org/publications/standards/Ecma-262.htm para conocer toda la historia detrás de estas pruebas de igualdad.
¿Otras lecturas?