En JavaScript, ¿por qué "0" es igual a falso, pero cuando se prueba con 'si' no es falso en sí mismo?
Lo siguiente muestra que "0"
es falso en Javascript:
>>> "0" == false
true
>>> false == "0"
true
Entonces, ¿por qué se imprime lo siguiente "ha"
?
>>> if ("0") console.log("ha")
ha
Tablas que muestran el problema:
y ==
Moraleja del uso de la historia ===
crédito de generación de tablas: https://github.com/dorey/JavaScript-Equality-Table
La razón es que cuando lo hace explícitamente "0" == false
, ambos lados se convierten en números y luego se realiza la comparación.
Cuando haces: if ("0") console.log("ha")
, se prueba el valor de la cadena. Cualquier cadena que no esté vacía es true
, mientras que una cadena vacía es false
.
Igual (==)
Si los dos operandos no son del mismo tipo , JavaScript los convierte y luego aplica una comparación estricta. Si cualquiera de los operandos es un número o un booleano , los operandos se convierten a números si es posible; de lo contrario, si alguno de los operandos es una cadena , el otro operando se convierte en una cadena si es posible. Si ambos operandos son objetos , JavaScript compara referencias internas que son iguales cuando los operandos se refieren al mismo objeto en la memoria.
(De los operadores de comparación de Mozilla Developer Network)
Es según especificaciones.
12.5 La declaración if ..... 2. Si ToBoolean(GetValue(exprRef)) es verdadero, entonces a. Devuelve el resultado de evaluar la primera Declaración. 3. De lo contrario, ....
ToBoolean, según la especificación, es
La operación abstracta ToBoolean convierte su argumento en un valor de tipo booleano según la Tabla 11:
Y esa tabla dice esto sobre las cadenas:
El resultado es falso si el argumento es la Cadena vacía (su longitud es cero); de lo contrario el resultado es verdadero
Ahora, para explicar por qué "0" == false
deberías leer el operador de igualdad, que establece que obtiene su valor de la operación abstracta, GetValue(lref)
coincide igual para el lado derecho.
Que describe esta parte relevante como:
si esPropertyReference(V), entonces a. Si HasPrimitiveBase(V) es falso, entonces sea get el método interno [[Get]] de la base; de lo contrario, sea get Sea el método interno especial [[Get]] definido a continuación. b. Devuelve el resultado de llamar al método interno get usando base como su valor y pasando GetReferencedName(V) para el argumento
O en otras palabras, una cadena tiene una base primitiva, que vuelve a llamar al método get interno y termina pareciendo falsa.
Si desea evaluar cosas usando la operación GetValue use ==
, si desea evaluar usando ToBoolean
, use ===
(también conocido como operador de igualdad "estricta")
Es PHP donde la cadena "0"
es falsa (falsa cuando se usa en un contexto booleano). En JavaScript, todas las cadenas que no están vacías son verdaderas.
El truco es que ==
contra un booleano no se evalúa en un contexto booleano, se convierte en un número y, en el caso de cadenas, eso se realiza analizando como decimal. Entonces obtienes Number 0
en lugar de la veracidad booleana true
.
Este es un diseño de lenguaje realmente pobre y es una de las razones por las que intentamos no utilizar el desafortunado ==
operador. Úselo ===
en su lugar.