¿Por qué (0 <5 <3) devuelve verdadero?


348

Estaba jugando en jsfiddle.net y tengo curiosidad por saber por qué esto se cumple.

if(0 < 5 < 3) {
    alert("True");
}

Entonces, esto:

if(0 < 5 < 2) {
    alert("True");
}

Pero esto no:

if(0 < 5 < 1) {
    alert("True");
}

¿Es esta peculiaridad alguna vez útil?


12
¿Conoces wtfjs.com ?
Harmen

1
¡Decir ah! No, nunca había visto eso antes.
punkrockbuddyholly

Ah, las alegrías de las conversiones de tipo implícito.
Jörg W Mittag el

44
Alguna vez util? Posiblemente por ofuscación. :-)
Icode4food

¿Por qué? Además, cualquier cosa es útil si solo puede encontrar las circunstancias que lo requieren. Es cierto que este se requiere con menos frecuencia que muchos otros, pero hay momentos, pocos y distantes entre sí, donde podría ser exactamente la herramienta para el trabajo.
temporary_user_name

Respuestas:


440

El orden de las operaciones hace (0 < 5 < 3)que se interprete en javascript como ((0 < 5) < 3)que produce (true < 3)y verdadero se cuenta como 1, lo que hace que devuelva verdadero.

Esta es también la razón por la que (0 < 5 < 1)devuelve falso, (0 < 5)devuelve verdadero, que se interpreta como 1, lo que resulta en (1 < 1).


158
Y porque JavaScript NO es Python. :-)
rsenna

1
Respondiste mientras estaba editando mi pregunta para agregar el if(0 < 5 < 1) == false. Todo está claro ahora, gracias :)
punkrockbuddyholly

28
Exactamente, Python es el único lenguaje que conozco que trata esta sintaxis ((0 < 5) && (5 < 3)), ya que probablemente haya otros, pero no los conozco.
Alan Geleynse el

18
@ Alan: Mathematica es otro ejemplo.
Joren

2
En mi humilde opinión, JavaScript debería generar TypeError al intentar comparar booleano con número, porque no tiene sentido.
Michał Perłakowski

63

Mi conjetura es porque 0 < 5es cierto, y true < 3se emite a lo 1 < 3que es cierto.


77
No hay casting aquí. Un cast es un operador, que el programador usa para verificar explícitamente un tipo. Esta es la conversión implícita de un booleano a un entero.
erickson el

44
@erickson, realmente ... ¿NECESITAMOS estar obsesionados con la semántica aquí?
CaffGeek el

2
No te preocupes por Erickson. También uso mal la palabra semántica. :)
Mateen Ulhaq

99
En cualquier caso, el término correcto es coerción . Y sí, Erickson está parcialmente equivocado con su certeza absoluta. Una coerción es, en cualquier caso, un tipo de conversión también si usualmente (pero es solo una convención) usa la palabra "conversión" para expresar conversiones de tipo explícitas. Tipo de conversión == Tipo de conversión.
Jack

1
Sofistas hasta el final ... La respuesta es 'lacónicamente' agradable de todos modos;)
Arman McHitarian

21

probablemente porque truese supone 1así

0 < 5 < 3  -->  true < 3 -->  1 < 3  --> true


10

En cuanto a su pregunta sobre si esta peculiaridad es útil alguna vez: supongo que podría haber algún caso en el que sería útil (si el código condensado es lo que busca), pero confiar en él (muy probablemente) reducirá severamente la comprensión de su código.

Es como usar post / pre increment / decrement como parte de expresiones más grandes. ¿Puedes determinar cuál es el resultado de este código de un vistazo?

int x = 5;
int result = ++x + x++ + --x;

Nota: con este código, a veces incluso puede obtener resultados diferentes según el idioma y el compilador.

Es una buena idea facilitarle la vida a usted y al próximo tipo que leerá su código. Escriba claramente lo que realmente quiere que suceda en lugar de confiar en los efectos secundarios como la conversión implícita de booleanos.


Por curiosidad, ¿tiene result18 años?
punkrockbuddyholly

55
@MrMisterMan: no estoy seguro acerca de Javascript, pero en Java y C # la evaluación se garantiza de izquierda a derecha, y el resultado es de hecho 18. En algunos lenguajes, como C y C ++, no hay garantía de que sea evaluado de izquierda a derecha, y puede terminar con diferentes resultados dependiendo de las optimizaciones agregadas por su compilador.
Zach Johnson el

9

La respuesta a la segunda parte de la pregunta, "¿alguna vez es útil esta peculiaridad?" tal vez sea no, como se señaló en una respuesta anterior, si de hecho es una peculiaridad del lenguaje (Javascript) que verdadero se convierte en 1, pero que el programador en general no ve 1 y verdadero (y 0 y falso) como el la misma cosa.

Sin embargo, si tiene un modelo mental de 1 siendo verdadero y 0 siendo falso, entonces conduce a todo tipo de buenas técnicas booleanas que son extremadamente útiles, poderosas y directas. Por ejemplo, podría incrementar un contador directamente con el resultado de A> 100, lo que incrementaría el contador si A es mayor que 100. Esta técnica podría verse como un capricho o un truco en Java, pero en una matriz o lenguaje funcional puede ser idiomático

Un ejemplo clásico en el lenguaje de matriz APL sería contar el número de elementos en una matriz que son (digamos) mayores que 100:

+/A>100

Donde si A es la matriz de 5 elementos 107 22 256 110 3 entonces:

A>100

produce la matriz booleana de 5 elementos:

1 0 1 1 0

y sumando este resultado booleano:

+/1 0 1 1 0

da la respuesta final:

3

Esta pregunta es un ejemplo perfecto de dónde esta técnica sería muy útil, especialmente si el problema se generaliza para determinar si n de m valores booleanos son verdaderos.

Compruebe si al menos dos de cada tres booleanos son verdaderos


7

Eso es fácil.

(0 < 5 < 3)

Comience de izquierda a derecha para evaluar el primer 0 <5. ¿Es cierto? Si. Como VERDADERO = 1, evalúa 1 <3. Dado que 1 es menor que 3, es cierto.

Ahora con esto

 (0 < 5 < 1)

¿Es 0 menos que 5? Si. Así que hazlo VERDADERO, lo que también significa 1. Ahora con ese hecho en mente, se evalúa como (1 <1). ¿1 es menos de 1? No, por lo tanto, es falso. Tiene que ser igual.


4

¿está evaluando 0 <5 que devolvería 1 para verdadero cuando 1 <3 que es verdadero?

C # quiere permitirte hacer esto "El operador '<' no se puede aplicar a operandos de tipo 'bool' e 'int'"


A veces extraño la rigurosidad de C # en lenguajes dinámicos.
Arman McHitarian

4

Me encontré con esto hace un tiempo en Obj-C y me sorprendió mucho. Obtuve los resultados que quería haciendo algo como esto:

if(0 < 5  && 5 < 3) {
alert("True");}

Lo cual, por supuesto, es falso para que no reciba esa alerta "verdadera". Me alegro de haber leído esto, ahora sé por qué.


4

Además de python, CoffeeScript es otro lenguaje que admite comparaciones encadenadas, por lo 3 < x < 10que se convertiría (3 < x && x < 10)en vanilla JS



1

Un operando booleano cuando se opera sobre un operador matemático devuelve un número. para comprobar esto hacemos

true + 1  which gives you 2.

Por lo tanto 0 < 5, el booleano devuelto (verdadero) operado con el operador matemático (<) devolverá un número. Entonces hierve a 1 <3 lo que devuelvetrue


1

porque 0 es menor que 5, entonces devuelve verdadero, y por defecto verdadero es cualquier cosa que incluye y puede evaluarse a 1, que aún es menor que 3, lo que nuevamente devuelve verdadero


0

intenta redactar tus resultados como Number ()

if(Number(0) < Number(5) < Number(3)) {
    alert("True");
}

o prueba esto:

if(Number(0) < Number(5) && Number(5) < Number(3)) {
    alert("True");
}

Busqué en Google esto porque estaba obteniendo (3 >= 20) //returning truey supongo que JavaScript estaba tratando de verificar 3como booleano porque estaba obteniendo este valor de la elm.getAttribute();función que console.log();se imprimía en forma de cadena.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.