Вход

Просмотр полной версии : true || undefined // true


andypop
13.05.2020, 13:06
Поясните пожалуйста почему?
var a=false
var b=true
var c=undefined
console.log((a || c)) //undefined
console.log((b || c))//true

Nexus
13.05.2020, 13:23
https://learn.javascript.ru/logical-operators

andypop
13.05.2020, 13:42
Это приводит к
console.log((a || c)!=(c || a)) //true

Nexus
13.05.2020, 14:15
Это приводит к
«Это» - это что?

andypop
13.05.2020, 15:35
Потому что булевы операторы предназначены для работы с булевыми значениями. А ваш var c=undefined не является булевым значением.


Т.е. в случае console.log((b || c)) // true является,
а в случае console.log((a || c)) // внезапно undefined

даже не false! Это просто фича такая:)

andypop
13.05.2020, 15:43
Я к чему это написал, что правильнее было бы сделать оба выражения учитывающих только операнды со значением , либо если один из операндов undefined, то и всё выражение тоже undefined

MallSerg
13.05.2020, 17:24
Я к чему это написал, что правильнее было бы сделать оба выражения учитывающих только операнды со знанием , либо если один из операндов undefined, то и всё выражение тоже undefined

Нет это чушь.
Правильно придерживаться спецификации языка
где операции над операндами совершаются согласно описанию
а приоритет операций согласно таблице приоритетов.

То что ты считаешь правильным поломает логику работы языка и приведет к различному поведению в различных ситуациях.

andypop
13.05.2020, 18:59
Нельзя поломать то, что уже поломано. И именно в булевых выражениях.
1+ undefined и undefined+1 даст одно и то же NaN. С точки зрения логики ассоциативность в языке не должна влиять на результат булевых выражений . Так что не чушь.

MallSerg
13.05.2020, 20:00
Ну так и используй плюс.
У логического или другой алгоритм работы.
Именно по этому плюс и возвращает NaN
А логическое "или" первое истинное значение из операндов.

andypop
14.05.2020, 15:14
Может вам нужно просвещение, что undefined — это не булево значение!
Вот именно. Как допустили, что не булево незначение участвует и влияет причем весьма странным образом в булевых операциях?

Malleys
14.05.2020, 16:56
Вот краткий пересказ своими словами из спецификации ECMAScript 2020 о том, как работают логические операторы.

ToBoolean ( аргумент )
Абстрактная операция ToBoolean принимает аргумент. Она преобразует аргумент в значение типа Boolean согласно следующей таблице:

┌─────────────── ──────────────── ──────────────── ─────────────┐
│ Тип аргумента │ Результат │
├─────────────── ──────────────── ──────────────── ─────────────┤
│ Undefined │ возвратить false │
├─────────────── ──────────────── ──────────────── ─────────────┤
│ Null │ возвратить false │
├─────────────── ──────────────── ──────────────── ─────────────┤
│ Boolean │ возвратить аргумент │
├─────────────── ──────────────── ──────────────── ─────────────┤
│ Number │ если аргумент равен +0, -0 или NaN, │
│ │ то возвратить false, иначе возвратить true │
├─────────────── ──────────────── ──────────────── ─────────────┤
│ String │ если аргумент является пустой строкой │
│ │ (её длина равна нулю), то возвратить false, │
│ │ иначе возвратить true │
├─────────────── ──────────────── ──────────────── ─────────────┤
│ Symbol │ возвратить true │
├─────────────── ──────────────── ──────────────── ─────────────┤
│ BigInt │ если аргумент равен 0n, то возвратить false, │
│ │ иначе возвратить true │
├─────────────── ──────────────── ──────────────── ─────────────┤
│ Object │ возвратить true │
└─────────────── ──────────────── ──────────────── ─────────────┘

Когда вычисляется A && B, то происходит следующее...

Если ToBoolean( A ) возвращает false, то вернуть A
иначе вернуть B


Когда вычисляется A || B, то происходит следующее...

Если ToBoolean( A ) возвращает true, то вернуть A
иначе вернуть B

andypop
14.05.2020, 17:36
Когда вычисляется A || B, то происходит следующее...
Если ToBoolean( A ) возвращает true, то вернуть A
иначе вернуть B

console.log((a || c)) //undefined
Если результат 'с' которое undefined - false какого он возвращает undefined
Согласно вашей же табличке результат вычисления 'c' в булевом выражении - false и общий результат должен быть false, а не undefined

Malleys
14.05.2020, 17:57
Согласно вашей же табличке результат вычисления 'c' в булевом выражении - false и общий результат должен быть false, а не undefined А где это вы увидели, что ToBoolean возвращает напрямую в качестве окончательного результата своё значение?

var a=false
var b=true
var c=undefined
console.log((a || c)) //undefined
console.log((b || c))//true


Я так понимаю (судя по коду выше), a || c у вас означает false || undefined . Смотрим...

Когда вычисляется A || B, то происходит следующее...

Если ToBoolean( A ) возвращает true, то вернуть A
иначе вернуть B


Подстанавливаем ваше выражение, получается...
Когда вычисляется (A = false) || (B = undefined), то происходит следующее...

Если ToBoolean( A = false ) возвращает true (а согласно таблице ToBoolean( A = false ) возвращает false), то вернуть A (поскольку условие не выполняется, смотрим далее)
иначе вернуть B (согласно подстановке, B было undefined, значит его и нужно вернуть)

Следовательно false || undefined === undefined

andypop
14.05.2020, 18:13
Ну т.е. для булевых выражений работают правила, а не табличка, согласно которой если аргумент undefined ,то результат false

andypop
14.05.2020, 18:39
Я вот и хотел, чтобы объяснили эту тонкость, а для булевых значений я в курсе. Речь идет об интерпретаторе, когда тип аргументов еще не известен. Можно использовать и правила js для toBoolean, но я против таких абстракций. фактически незначение undefined приравнено к значению. Хотя по идее если от значения undefined зависит результат булевой операции нужно возвращать undefined. Понятно, что правила сделаны в угоду синтаксису. Но ...

voraa
15.05.2020, 08:10
Нельзя поломать то, что уже поломано. И именно в булевых выражениях.
1+ undefined и undefined+1 даст одно и то же NaN. С точки зрения логики ассоциативность в языке не должна влиять на результат булевых выражений . Так что не чушь.
В JS нет понятия ассоциативности. Это не математика.
Все операции выполняются так, как они записаны, с учетом лево или правосторонности.
Операция + ни грамма не ассоциативная.
1+ "0" и "0" + 1

Операции && и || не булевы, а логические. Так они названы в спецификации.
Булевые операции подразумевали бы, что их операнды должны иметь тип boolean и выдавать такой же результат.

Как допустили, что не булево незначение участвует и влияет причем весьма странным образом в булевых операциях?
Это не незначение, а именно значение.
В JS есть тип undefined (такой же как Number, String, Boolean) с единственным значением undefined

laimas
15.05.2020, 08:53
В JS нет понятия ассоциативности.

В контексте приоритета операторов или?

voraa
15.05.2020, 09:26
В контексте приоритета операторов или?
Что такое приоритет?
В спецификации нет такого понятия.

laimas
15.05.2020, 09:57
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

voraa
15.05.2020, 10:32
mdn хорошая вещь.
Но это не спецификация, а только ее трактовка. Иногда не совсем полная.

laimas
15.05.2020, 11:22
это не спецификация, а только ее трактовка

То есть о приоритетах это выдумка? :) Так что или чем тогда определяется порядок выполнения операторов, а также что такое в случае операторов с одинаковым приоритетом (примечание: термин имеет статус нелегального)?

Malleys
15.05.2020, 11:26
Операции && и || не булевы, а логические. Так они названы в спецификации. Булевые операции подразумевали бы, что их операнды должны иметь тип boolean и выдавать такой же результат.Булевы операции, или логические операции в первую очередь и предназначены для работы с булевым типом данных, или логическим типом данных. Это одно и тоже — Boolean или logical data type. Логический тип данных ещё называют булевым типом в честь английского математика и логика Джорджа Буля.

Операция + ни грамма не ассоциативная. Опять же, вы не учитываете типы! Когда и правый и левый операнды имеют одинаковый тип (String, Number или BigInt соответственно), то выполняется ассоциативность. В спецификации указано, что операция + в конечном счёте производит конкатенацию строк или сложение чисел. (https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator)

alert(("a" + "b") + "c" === "a" + ("b" + "c")); // true, поскольку ассоциативность выполняется
alert((1 + 2) + 3 === 1 + (2 + 3)); // true, поскольку ассоциативность выполняется
alert((1 + 1) + "1" === 1 + (1 + "1")); // false, вы конечно можете и тут подобрать true, но тут разные типы, это плохая практика — отстреливать себе ноги и играть с мухой без головы, понапихают разного рандомного говна в операнды, а потом сидят и задают тупые вопросы, типа а почему там нет ассоциативности!

Так что или чем тогда определяется порядок выполнения операторов В спецификации указаны правила разбора выражении рядом с алгоритмом выполнения (Runtime Semantics: Evaluation)

laimas
15.05.2020, 11:41
В спецификации указаны правила разбора выражении рядом с алгоритмом выполнения

Вот тут вопрос - то что описано в спецификации верно по смыслу тому, что поясняется терминами "приоритет" и "ассоциативность" или же эти термины далеки от истины и нужно следовать "букве закона" отбросив их?

voraa
15.05.2020, 13:16
В спецификации указаны правила разбора выражении рядом с алгоритмом выполнения (Runtime Semantics: Evaluation)
Опять же, вы не учитываете типы! Когда и правый и левый операнды имеют одинаковый тип (String, Number или BigInt соответственно), то выполняется ассоциативность.
Вот с этим четким алгоритмом и надо действовать.
В нем ничего не говорится, что если типы одинаковы, то есть ассоциативность, а если разные то ассоциативности нет...
Просто есть алгоритм, как выполняется операция с учетом возможных типов

voraa
15.05.2020, 14:10
Вот тут вопрос - то что описано в спецификации верно по смыслу тому, что поясняется терминами "приоритет" и "ассоциативность" или же эти термины далеки от истины и нужно следовать "букве закона" отбросив их?

Приоритет определяется грамматикой языка.
Но про ассоциативность в программировании просто говорить бессмысленно. Так же, как и про коммутативность.
a+(b+c) == (a+b)+c ?
a+b == b+a ?
Когда как.
Мы же не знаем, что такое а, b, c.
А может быть это вызовы функций с побочным эффектом?
Просто есть правила выполнения операций.
a * b
Вычисли а, приведи к числовому типу
Вычисли b, приведи к числовому типу
(именно в такой последовательности, а не наоборот)
Результаты арифметически перемножь

laimas
15.05.2020, 14:25
Приоритет определяется грамматикой языка.

И что это означает, определен ли в JS приоритет операторов? Учебники, справочные материалы языка оперируют именно приоритетом и ассоциацией операторов, и не просто рассказывают, а определены таблицей приоритетов. Тогда тут либо игра слов, либо упираемся рогом и не пяди не отдадим, либо то что заложено в сами понятия приоритет и ассоциация в JS не приемлемо и гарантированно будет порождать ошибки. Так что такое тогда приоритет и ассоциация в контексте операторов?

andypop
15.05.2020, 15:16
Malleys всё чётко объяснил, зачем это мозгоблудие? И приоритет есть для операндов и ассоциативность. Все дело именно в применение toBoolean. для js оно такое. Возможно что-то похожее есть и в др. языках. Давайте закруглять тему.