Чому (0 <5 <3) повертає істину?


348

Я грав на jsfiddle.net і мені цікаво, чому це повертається правдою?

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

Так і відбувається:

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

Але це не так:

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

Чи корисна ця примха?


12
Чи знаєте ви wtfjs.com ?
Хармен

1
Га! Ні, я ніколи цього не бачив.
punkrockbuddyholly

Ах, радості неявних типів перетворень.
Йорг W Міттаг

4
Колись корисна? Можливо для опущення. :-)
Icode4food

Чому? Також будь-що корисне, якщо ви зможете знайти лише ті обставини, які цього вимагають. Правда, цей рідше вимагається, ніж багато інших, але буває мало, і між ними буває мало, хоча вони можуть бути саме інструментом для роботи.
тимчасовий_користувач

Відповіді:


440

Порядок операцій спричиняє (0 < 5 < 3)інтерпретацію JavaScript у тому, ((0 < 5) < 3)що виробляє (true < 3)та істинно, зараховується як 1, що призводить до повернення істини.

Це також, чому (0 < 5 < 1)повертає false, (0 < 5)повертає true, що інтерпретується як 1, в результаті чого (1 < 1).


158
А тому що JavaScript НЕ є Python. :-)
rsenna

1
Ви відповіли, коли я редагував моє запитання, щоб додати тему if(0 < 5 < 1) == false. Тепер все зрозуміло, спасибі :)
punkrockbuddyholly

28
Точно так, Python є єдиною мовою, яку я знаю, що трактує цей синтаксис як ((0 < 5) && (5 < 3)), мабуть, є й інші, але я не знаю їх.
Алан Геленсе

18
@Alan: Математика - ще один приклад.
Joren

2
IMHO JavaScript повинен підняти TypeError, намагаючись порівнювати булевий з числом, оскільки це не має сенсу.
Michał Perłakowski

63

Я думаю, тому що 0 < 5це правда, і true < 3отримує кидок на 1 < 3який вірно.


7
Тут немає кастингу. Каст - це оператор, який програміст використовує для явної перевірки типу. Це неявне перетворення з булевого в ціле число.
erickson

4
@erickson, насправді ... чи НЕМОЖЕ бути тут повішених на семантику?
CaffGeek

2
Не хвилюйтесь про еріксона. Я також неправильно використовую слово семантичний. :)
Mateen Ulhaq

9
У будь-якому випадку правильним терміном є примус . І так, Еріксон частково неправильний з його абсолютною впевненістю. Примус у будь-якому випадку є роллю також, якщо зазвичай (але це лише умова) ви використовуєте слово "лити" для вираження конверсій явного типу. Перетворення типу == Лиття типу.
Джек

1
Софісти до кінця ... Відповідь все одно "лаконічно" приємна;)
Арман Макгітарін

21

ймовірно, тому true, що передбачається 1таким

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


10

Що стосується вашого запитання, чи корисна ця витівка: я вважаю, що може бути корисною ситуацію (якщо стислий код - це те, що ви шукаєте), але покладаючись на нього, (швидше за все), це значно знизить зрозумілість вашого коду.

Це схоже на використання пост / попереднього збільшення / декременту як частини більшого вираження. Чи можете ви з першого погляду визначити, який результат цього коду?

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

Примітка. За допомогою цього коду ви можете іноді навіть отримувати різні результати, залежно від мови та компілятора.

Це гарна ідея, щоб полегшити життя собі та наступному хлопцеві, який прочитає ваш код. Чітко випишіть, що ви насправді хочете, щоб сталося, а не покладалися на такі побічні ефекти, як неявна конверсія булів.


З цікавості result18?
punkrockbuddyholly

5
@MrMisterMan: Я не впевнений у Javascript, але в Java та C # оцінка гарантується зліва направо, а результат дійсно 18. У деяких мовах, таких як C та C ++, немає гарантії, що це буде оцінюється зліва направо, і ви можете отримати різні результати залежно від оптимізації, доданої вашим компілятором.
Зак Джонсон

9

Відповідь на другу частину питання "чи корисна ця примха?" це, мабуть, ні, як зазначалося в попередній відповіді, якщо це дійсно вигадка мови (Javascript), що true передається до 1, але що програміст загалом не переглядає 1, а true (і 0 і false) як однакові речі.

Якщо ж у вас є ментальна модель: 1 є правдою, а 0 - хибною, то це призводить до всіляких приємних бульних методів, які є надзвичайно корисними, потужними та прямими. Наприклад, ви можете збільшити лічильник безпосередньо з результатом A> 100, що збільшило б лічильник, якщо A більше 100. Ця техніка може розглядатися як химерність або хитрість на Java, але в масиві або функціональній мові може бути ідіоматичним.

Класичним прикладом APL мови масиву може бути підрахунок кількості елементів у масиві, що (скажімо) перевищує 100:

+/A>100

Де, якщо A - це масив 5 елементів 107 22 256 110 3, тоді:

A>100

виходить бульовий масив з 5 елементів:

1 0 1 1 0

і підбиття цього булевого результату:

+/1 0 1 1 0

дає остаточну відповідь:

3

Це питання є прекрасним прикладом, коли ця методика була б дуже корисною, особливо якщо проблема узагальнена для визначення того, чи n з m булевих значень істинно.

Перевірте, чи принаймні два з трьох булевих значень справжні


7

Це легко.

(0 < 5 < 3)

Почніть зліва направо, щоб вона оцінювала перші 0 <5. Це правда? Так. Оскільки ІСТИНА = 1, вона оцінює 1 <3. Оскільки 1 менше 3, то це правда.

Тепер з цим

 (0 < 5 < 1)

Чи 0 менше 5? Так. Отже, зробіть це ІСТИНО, що також означає 1. Тепер, маючи на увазі цей факт, він оцінює до (1 <1). Чи на 1 менше 1? Ні, тому це помилково. Він повинен бути рівним.


4

чи оцінює 0 <5, що поверне 1 для істинного, коли 1 <3, що відповідає дійсності?

C # хочу дозволити вам зробити це "Оператор" <"не можна застосовувати до операндів типу" bool "і" int ""


Іноді я пропускаю строгість C # у динамічних мовах.
Арман Макгітарін

4

Я натрапив на це трохи раніше тому в Obj-C і був дуже спантеличений цим. Я отримав потрібні результати, зробивши щось подібне:

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

Що, звичайно, помилково, щоб ви не отримали це "справжнє" попередження. Радий, що я це прочитав, тепер знаю, чому.


4

На додаток до python, CoffeeScript - ще одна мова, яка підтримує ланцюгові порівняння, таким чином 3 < x < 10перетворюється на (3 < x && x < 10)ванільний JS



1

Булевий операнд при роботі з математичним оператором повертає число. щоб перевірити це ми робимо

true + 1  which gives you 2.

Отже 0 < 5, повернута булева (справжня), оперована з математичним оператором (<), поверне число. Отже, вона кипить до 1 <3, яка повертаєтьсяtrue


1

тому що 0 менше 5, то це повертає істину, а за замовчуванням істина - це все, включаючи і може бути оцінено до 1, який все ще менше 3, що знову повертає істину


0

спробуйте сформулювати результати як номер ()

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

або спробуйте це:

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

Я переглянув це через Google, тому що я отримував, (3 >= 20) //returning trueі я думаю, що JavaScript намагався перевірити 3як булевий, тому що я отримував це значення з elm.getAttribute();функції, яка console.log();друкувалася у String формі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.