Por que (0 <5 <3) retorna verdadeiro?

348

Eu estava brincando no jsfiddle.net e estou curioso para saber por que isso retorna verdadeiro?

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

O mesmo acontece com isso:

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

Mas isso não acontece:

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

Essa peculiaridade é sempre útil?

punkrockbuddyholly
fonte
12
Você conhece wtfjs.com ?
Harmen
11
Ha! Não, eu nunca tinha visto isso antes.
precisa
Ah, as alegrias das conversões implícitas de tipo.
Jörg W Mittag
4
Sempre útil? Possivelmente por ofuscação. :-)
Icode4food
Por quê? Além disso, qualquer coisa é útil se você puder encontrar apenas as circunstâncias que a exigem. É verdade que este é menos necessário do que muitos outros, mas há momentos, muito poucos e distantes, onde possam estar, onde pode ser exatamente a ferramenta para o trabalho.
temporary_user_name

Respostas:

440

A ordem das operações faz (0 < 5 < 3)com que seja interpretado em javascript como o ((0 < 5) < 3)que produz (true < 3)e true é contado como 1, fazendo com que ele retorne true.

É também por isso que (0 < 5 < 1)retorna false, (0 < 5)retorna true, que é interpretado como 1resultando em (1 < 1).

Alan Geleynse
fonte
158
E porque o JavaScript NÃO é Python. :-)
rsenna
11
Você respondeu enquanto eu estava editando minha pergunta para adicionar o if(0 < 5 < 1) == false. Tudo está claro agora, graças :)
punkrockbuddyholly
28
Exatamente, Python é a única linguagem que conheço que trata essa sintaxe ((0 < 5) && (5 < 3)), pois provavelmente existem outras, mas eu não as conheço.
Alan Geleynse
18
@ Alan: Mathematica é outro exemplo.
Joren
2
O IMHO JavaScript deve gerar TypeError ao tentar comparar booleano com número, porque não faz sentido.
Michał Perłakowski
63

Meu palpite é que 0 < 5é verdade, e true < 3é lançado para o 1 < 3que é verdadeiro.

CaffGeek
fonte
7
Não há elenco aqui. Uma conversão é um operador que o programador usa para verificar explicitamente um tipo. Isso é conversão implícita de um booleano para um número inteiro.
quer
4
@ erickson, sério ... PRECISAMOS de ficar pendurados na semântica aqui?
CaffGeek #
2
Não se preocupe com Erickson. Também uso indevidamente a palavra semântica. :)
Mateen Ulhaq
9
De qualquer forma, o termo correto é coerção . E sim, Erickson está parcialmente errado com sua absoluta certeza. De qualquer forma, uma coerção também é um tipo de conversão, se normalmente (mas é apenas uma convenção) você usa a palavra "conversão" para expressar conversões de tipo explícitas. Conversão de tipo == Conversão de tipo.
Jack
11
Sofistas todo o caminho ... A resposta é 'laconicamente' bom de qualquer maneira;)
Arman McHitarian
21

provavelmente porque trueé assumido como 1tão

0 < 5 < 3  -->  true < 3 -->  1 < 3  --> true
Jack
fonte
17

Porque true < 3porquetrue == 1

Harmen
fonte
10

Quanto à sua pergunta sobre se essa peculiaridade é útil: suponho que possa haver algum caso em que seja útil (se for o que você procura depois de código condensado), mas confiar nele irá (muito provavelmente) reduzir drasticamente a compreensibilidade do seu código.

É como usar pós / pré-incremento / decremento como parte de expressões maiores. Você pode determinar rapidamente qual é o resultado desse código?

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

Nota: com esse código, às vezes você pode obter resultados diferentes dependendo do idioma e do compilador.

É uma boa idéia facilitar a vida para você e o próximo cara que lerá seu código. Escreva claramente o que você realmente quer que aconteça, em vez de depender de efeitos colaterais, como a conversão implícita de booleanos.

Zach Johnson
fonte
Por curiosidade, tem result18 anos?
precisa
5
@MrMisterMan: Não tenho certeza sobre Javascript, mas em Java e C # a avaliação é garantida da esquerda para a direita e o resultado é realmente 18. Em algumas linguagens, como C e C ++, não há garantia de que será avaliado da esquerda para a direita e você pode ter resultados diferentes, dependendo das otimizações adicionadas pelo seu compilador.
Zach Johnson
9

A resposta para a segunda parte da pergunta "essa peculiaridade é sempre útil?" talvez não, como observado em uma resposta anterior, se é realmente uma peculiaridade da linguagem (Javascript) que true é convertido em 1, mas que o programador não vê em geral 1 e true (e 0 e false) como o mesma coisa.

Se, no entanto, você tem um modelo mental de 1 sendo verdadeiro e 0 sendo falso, isso leva a todo tipo de boas técnicas booleanas que são extremamente úteis, poderosas e diretas. Por exemplo, você pode incrementar um contador diretamente com o resultado de A> 100, o que aumentaria o contador se A for maior que 100. Essa técnica pode ser vista como uma peculiaridade ou um truque em Java, mas em uma matriz ou linguagem funcional pode ser idiomático.

Um exemplo clássico no idioma da matriz APL seria contar o número de itens em uma matriz que são (digamos) maiores que 100:

+/A>100

Onde A é a matriz de 5 itens 107 22 256 110 3, então:

A>100

gera a matriz booleana de 5 itens:

1 0 1 1 0

e somando esse resultado booleano:

+/1 0 1 1 0

produz a resposta final:

3

Esta pergunta é um exemplo perfeito de onde essa técnica seria muito útil, especialmente se o problema for generalizado para determinar se n de valores booleanos são verdadeiros.

Verifique se pelo menos dois de três booleanos são verdadeiros

PAUL Mansour
fonte
7

Isso é fácil.

(0 < 5 < 3)

Comece da esquerda para a direita para avaliar o primeiro 0 <5. É verdade? Sim. Como TRUE = 1, ele avalia 1 <3. Como 1 é menor que 3, é verdade.

Agora com isso

 (0 < 5 < 1)

0 é menor que 5? Sim. Portanto, torne VERDADEIRO o que também significa 1. Agora, com esse fato em mente, ele avalia como (1 <1). 1 é menor que 1? Não, portanto, é falso. Tem que ser igual.

netrox
fonte
4

está avaliando 0 <5 que retornaria 1 como verdadeiro quando 1 <3 que é verdadeiro?

C # quer que você faça isso "O operador '<' não pode ser aplicado a operandos do tipo 'bool' e 'int'"

David
fonte
Às vezes, sinto falta do rigor do C # em linguagens dinâmicas.
Arman McHitarian
4

Eu me deparei com isso há pouco tempo no Obj-C e fiquei muito intrigado com isso. Consegui os resultados desejados fazendo algo assim:

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

O que, obviamente, é falso, para que você não receba esse alerta "verdadeiro". Ainda bem que li isso, agora sei o porquê.

Hipócrates
fonte
4

Além do python, o CoffeeScript é outra linguagem que suporta comparações encadeadas e, portanto, 3 < x < 10seria convertida (3 < x && x < 10)em JS vanilla

Hipócrates
fonte
3
0 < 5 < 3 
==> ( ( 0 < 5 ) < 3 )
==> true < 3
==> 1 < 3
==> true
truease.com
fonte
1

Um operando booleano quando operado sobre um operador matemático retorna um número. para verificar isso, fazemos

true + 1  which gives you 2.

Portanto 0 < 5, o booleano retornado (true) operado com o operador matemático (<) retornará um número. Então, ele chega a 1 <3, que retornatrue

Rajkamal Subramanian
fonte
1

porque 0 é menor que 5, então retorna true, e por padrão true é qualquer coisa que inclua e possa ser avaliado como 1, que ainda é menor que 3, que retorna novamente true

ndoty
fonte
0

tente redigir seus resultados como Number ()

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

ou tente o seguinte:

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

Eu pesquisei isso porque estava recebendo (3 >= 20) //returning truee acho que o javascript estava tentando verificar 3como um booleano porque estava obtendo esse valor da elm.getAttribute();função que console.log();estava sendo impressa no formato String.

SwiftNinjaPro
fonte