Javascript chained inequality gives bizarre results [duplicate] - javascript

This question already has answers here:
Can I use chained comparison operator syntax? [duplicate]
(6 answers)
Closed 8 years ago.
(0 <= 0 <= 0) === false
(-1 < 0 <= 0 <= 0) === true
What's going on here? Does Javascript actually have inequality chaining that's just wrong in some cases?

Typed up the question and then was struck by the answer. Javascript does not have inequality chaining. Rather, 0 <= 0 <= 0 becomes true <= 0, which is evaluated as 1 <= 0. Indeed, 0 < 0 <= 0 evaluates to true.

There is no chaining of operator but precedence. Here all the operators have the same priority so the operations are done from left to right.
When your comparison involves a boolean, the MDN explains how the comparison works :
If one of the operands is Boolean, the Boolean operand is converted to
1 if it is true and +0 if it is false.
This means the first operation is decomposed according to priorities as
((0 <= 0) <= 0)
which is
true <= false
which is
false
And the second one is
(true <= 0) <= 0
which is
false <= 0
which is true.

Related

isEven function wierd way [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 8 months ago.
Improve this question
I was playing around with on of the excercises when I coded this:
function isEven(x){
var m = x % 2
var n = x / 2
return m <= !n
}
The funny part is that it actually works, but I do not understand if !n makes the number negative or affects the boolean value itself. Can someone explain how my code works? Thanks.
!n is a red herring. For any value of x other than 0, !n will be false; it will be true when x == 0.
m is 0 for even numbers, 1 for odd numbers. When you compare a number with a boolean, the boolean is converted to a number. So m <= false is equivalent to m <= 0. This will be true when m is 0.
So you can get rid of n and just use this:
function isEven(x){
var m = x % 2;
return m <= false
}
[0, 1, 2, 3, 4, 5, 6, 7, 8].forEach(x => console.log(x, isEven(x)));
The reason why it works with !n is because in the only case where !n is true, x == 0 and m == 0. 0 <= true is true, so the function returns the correct result then as well.
First
var n = x / 2
n will be falsey if x is 0, and truthy otherwise.
If the argument is even and not 0:
m will be 0
n will be a truthy number (because anything divided by 2 is another non-zero number - except 0)
!n will be false (because that's the boolean inverse of 0, a falsey value)
the return statement is 0 <= false; false gets converted into a number when compared with <=, and 0 <= 0 is true
If the argument is odd and positive:
m will be 1
n will be truthy (because any odd number divided by 2 is another non-zero number, and a non-zero number is truthy)
!n will be false (because that's the boolean inverse of a truthy value)
the return statement is 1 <= false; false gets converted into a number when compared with <=, and 1 <= 0 is false
If the argument is even and 0:
m will be 0
n will be 0
!n will be true (boolean inverse of 0)
the return statement is 0 <= true; true gets converted into a number when compared with <=, and 0 <= 1 is true
But the code doesn't work when the argument is odd and negative, because a negative odd number % 2 gives -1, not 1.
m will be -1
n will be truthy (because any odd number divided by 2 is another non-zero number, and a non-zero number is truthy)
!n will be false (because that's the boolean inverse of a truthy value)
the return statement is -1 <= false; false gets converted into a number when compared with <=, and -1 <= 0 is true - when it should be false

Why is 1<x<3 always true?

I'm learning TypeScript, and in the getting started page, they talk about how unexpected javascript is.
Source: https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html
if ("" == 0) {
// It is! But why??
}
if (1 < x < 3) {
// True for *any* value of x!
}
But I still don't understand why 1<x<3 is always true? For example if I let x=10, it will not be true by logic, but why they said it always true?
1 < x < 3 actually is doing this:
(1 < x) < 3
Or even more long form:
const tempVarA = 1 < x
const tempVarB = tempVarA < 3
So 1 < x is either true or false. Then the next step is true < 3 or false < 3. Those don't make much sense as comparisons, but let's see what javascript does with that:
console.log(true < 3) // true
console.log(false < 3) // true
Weird, but let's dig deeper:
console.log(true >= 0) // true
console.log(true >= 1) // true
console.log(true >= 2) // false
console.log(false >= 0) // true
console.log(false >= 1) // false
console.log(false >= 2) // false
It seems that true is being treated as 1 and false is being treated as 0. To verify that let's compare with == (instead of ===) so that it coerces the type of the data for us.
console.log(true == 1) // true
console.log(true == 0) // false
console.log(false == 1) // false
console.log(false == 0) // true
So 1 < x < 3 is always true because false becomes 0 or true becomes 1, and both 0 and 1 always less than 3.
Explanation:
in javascript, comparison operators <, <=, >, >=, ==, and != coerce their operands to make them comparable when they are different types. So when comparing a boolean to a number it coverts the boolean to a number, 0 or 1.
This is why you should almost always use === instead of ==, and why this is a type error in typescript:
const a = true < 3
// Operator '<' cannot be applied to types 'boolean' and 'number'.(2365)
Short version
Javascript and typescript lack a chainable comparison operator.
Did you mean to do this?
1 < x && x < 3
in other words: true is 1 and false is 0. Therefore 1 < x < 3 with x = 5 is as if it executes (1 <5) <3 and writes to 1 <5 = 1 (true) and then 1 <3 = 1 (true). If instead x were 0? Ok 1 <0 is false (0) consequently 0 <3 is true (1)

Are multiple comparison operators possible in javascript? [duplicate]

This question already has answers here:
Dual or triple (or even multiple) comparison in JavaScript
(3 answers)
Closed 2 years ago.
So i was writing in the Browser console
4 < 5
true
4 < 5 < 10
true
7 < 4 < 10
true
The first two statements look ok, why is the last statement also correct? I would have thought (as in mathematics) the expression would be 'AND'ed ? can any one point me to MDN or similar resource which talks about this and the rules ?
What Javascript does, is evaluate the left side first:
4 < 5 => true
It then continues on the rest:
true < 10 => true
because true on the left side is coerced to a number (1), and 1 < 10 === true. (false in comparisons with numbers is coerced to 0).
Check these funny-looking "goofs":
console.log(3 < 2 < 1)
console.log(1 < 1 < 1)
Beside the not working approach to write a continuing check with more than one copmparison operator, and while the next comparison takes place the the result of the previous comparison, you could take an array and a function for the comparison operator and iterate the items for every pair to check. Then return the result.
const compare = (values, fn) => values.slice(1).every((b, i) => fn(values[i], b));
console.log(compare([7, 4, 10], (a, b) => a < b)); // false
console.log(compare([4, 7, 10], (a, b) => a < b)); // true
console.log(compare([2, 1, 0], (a, b) => a > b)); // true
console.log( false < 10) // true
console.log( true < 10) // true
because false (0) is less than to 10
and true (1) is also less than to 10.
4 < 5 evaluates to true. Then true is compared with 10. Javascript converts true to 1 and as 1 is smaller than 10 the result is true.
With this logic if you try 4 < 5 < 3 this will also return true with the same logic, and 4 < 5 < 1 will return false.

What does shorthand "index >= 0 && count++" do?

I was killing time reading the underscore.string functions, when I found this weird shorthand:
function count (str, substr) {
var count = 0, index;
for (var i = 0; i < str.length;) {
index = str.indexOf(substr, i);
index >= 0 && count++; //what is this line doing?
i = i + (index >= 0 ? index : 0) + substr.length;
}
return count;
}
Legal: Think twice before using the function above without giving credit to underscore.string
I put the line alone here, so you don't waste time finding it:
index >= 0 && count++;
I have never seen anything similar to that. I am clueless in what is doing.
index >= 0 && count++;
First part: index >= 0
returns true if index has a value that is greater than or equal to 0.
Second part: a && b
most C-style languages shortcut the boolean || and && operators.
For an || operation, you only need to know that the first operand is true and the entire operation will return true.
For an && operation, you only need to know that the first operand is false and the entire operation will return false.
Third Part: count++
count++ is equivalent to count += 1 is equivalent to count = count + 1
All together now
If the first operand (index >= 0) of the line evaluates as true, the second operand (count++) will evaluate, so it's equivalent to:
if (index >= 0) {
count = count + 1;
}
JavaScript nuances
JavaScript is different from other C-style languages in that it has the concept of truthy and falsey values. If a value evaluates to false, 0, NaN, "", null, or undefined, it is falsey; all other values are truthy.
|| and && operators in JavaScript don't return boolean values, they return the last executed operand.
2 || 1 will return 2 because the first operand returned a truthy value, true or anything else will always return true, so no more of the operation needs to execute. Alternatively, null && 100 will return null because the first operand returned a falsey value.
It's equivalent to:
if (index >= 0) {
count = count + 1;
}
&& is the logical AND operator. If index >= 0 is true, then the right part is also evaluated, which increases count by one.
If index >= 0 is false, the right part is not evaluated, so count is not changed.
Also, the && is slightly faster than the if method, as seen in this JSPerf.
It's the same as:
if(index >= 0){
count++;
}
JavaScript will evaluate the left side (index >= 0), if it's false the && (AND) will short circuit (since false AND anything is false), thus not running `count++.
If it's (index >= 0) true, it evaluates the right side (count++), then it just ignores the output.

How come this is true? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why does (0 < 5 <3) return true?
How come this is true?:
console.log(100 < 210 < 200); // outputs true
That's equivalent to:
console.log((100 < 210) < 200);
which is equivalent to:
console.log(true < 200);
And this evaluates to true because when using operators like <, true is treated as if it were a 1
Consequently, the following will evaluate to false:
console.log(true < 0)
100 < 210 < 200 is equivalent to (100 < 210) < 200 which is true < 200 which is 1 < 200 which is true.
That last bit (true becoming 1) may be a bit surprising. It's the result of how JavaScript does relational operations (Section 11.8.5 of the spec), which says amongst other things that if the relation is between a non-number (other than null or undefined) and a number, you convert the non-number to a number, and the conversion of true to a number results in 1 (Section 9.3 of the spec.)

Categories

Resources