Why is 1<x<3 always true? - javascript

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)

Related

Recursive method keeps going, but in the opposite direction. Why?

So I'm trying to familiarize myself with recursion and Javascript. So I wrote a simple method to try it out. I'm pretty new to Javascript syntax so I'm not really sure where I'm going wrong. Here is the method.
export const IsEven = (n) => {
if(n > 1){
n -= 2;
IsEven(n);
}
else{
var bool = NumberToBool(n);
return bool;
}
}
When stepping through, n does reach 0 or 1 and defines it as true or false. However, the method does not stop at the return statement. Instead, it turns around and starts adding 2 to n. I cannot understand how that is even possible, does anyone have an idea on what is going on?
Thanks
You can use mathematical induction to solve the vast majority of recursive problems -
if n is negative, return the result of isEven(-n)
(inductive) n is zero or greater. if n is greater than one, return the result of the recursive sub-problem, isEven(n - 2)
(inductive) n is neither negative nor greater than 1. this means n is zero or one. zero is even, one is odd. return n == 0 gives us the correct result for both.
const isEven = (n) => {
if (n < 0) return isEven(n * -1) // 1. n is negative
else if (n > 1) return isEven(n - 2) // 2. n is 2 or more
else return n == 0 // 3. n is 0 or 1
}
for (let i = -10; i<10; i++)
console.log(i, isEven(i))
Recursion is a functional heritage and so using it with functional style yields the best results. if statements do not evaluate to a value and instead rely on side effects like return to compute the result. Below we use expressions which evaluate to a value and it allows us to skip a lot of the syntactic noise that comes with imperative style. Now isEven reads more like a formula -
const isEven = n =>
n < 0
? isEven(n * -1) // 1. n is negative
: n > 1
? isEven(n - 2) // 2. n is 2 or more
: n == 0 // 3. n is 0 or 1
for (let i = -5; i < 5; i++)
console.log(i, isEven(i))
n
isEven(n)
-5
false
-4
true
-3
false
-2
true
-1
false
0
true
1
false
2
true
3
false
4
true
isEven can be defined using a synergistic counterpart, isOdd, where each can be defined in terms of the other. This technique is called mutual recursion -
const isEven = n =>
n < 0
? isEven(-n)
: n == 0
? true
: isOdd(n - 1)
const isOdd = n =>
n < 0
? isOdd(-n)
: n == 0
? false
: isEven(n - 1)
for (let i = -5; i < 5; i++)
console.log(`i:${i} isEven:${isEven(i)} isOdd:${isOdd(i)}`)
n
isEven(n)
isOdd(n)
-5
false
true
-4
true
false
-3
false
true
-2
true
false
-1
false
true
0
true
false
1
false
true
2
true
false
3
false
true
4
true
false

Why does comparing value with undefined returns false in JavaScript?

I am new to Javascript and I noticed when a variable is undefined, comparing a number returns false as below. Why does comparing undefined with numbers return false?
var a = undefined;
console.log(a < 10);
console.log(10 < a);
console.log(a == 10);
This is how works in JavaScript.
Number(undefined) // NaN
NaN == NaN // false
NaN < 0 // false
NaN > 0 // false
So, while you compare it forces to check like:
Number(undefined) < 10
// undefined is coerced to check with number
And thus,
undefined == 10 // false
undefined > 10 // false
undefined < 10 // false

Multiple strict equality comparisons in a single line

I have the following JavaScript code:
var a = 1;
var b = 1;
a === 1 // evaluates to true
b === 1 // evaluates to true
a == b == 1 // evaluates to true
a === b === 1 // evaluates to false
Why does a === b === 1 evaluate to false?
a == b == 1
is evaluated as
((a == b) == 1)
Since a == b is true, the expression becomes
true == 1
Since == does type coercing, it converts true to a number, which becomes 1. So the expression becomes
1 == 1
That is why this expression is true. You can confirm the boolean to number conversion like this
console.log(Number(true));
// 1
console.log(Number(false));
// 0
Similarly,
a === b === 1
is evaluated as
((a === b) === 1)
so
true === 1
Since === doesn't do type coercion (as it is the strict equality operator), this expression is false.

How does (A == B == C) comparison work in JavaScript?

I was expecting the following comparison to give an error:
var A = B = 0;
if(A == B == 0)
console.log(true);
else
console.log(false);
but strangely it returns false.
Even more strangely,
console.log((A == B == 1));
returns true.
How does this "ternary" kind of comparison work?
First, we need to understand that a == comparison between a number and a boolean value will result in internal type conversion of Boolean value to a number (true becomes 1 and false becomes 0)
The expression you have shown is evaluated from left to right. So, first
A == B
is evaluated and the result is true and you are comparing true with 0. Since true becomes 1 during comparison, 1 == 0 evaluates to false. But when you say
console.log((A == B == 1));
A == B is true, which when compared with number, becomes 1 and you are comparing that with 1 again. That is why it prints true.
Assignment operators like = are right-associative: when there is a series of these operators that have the same precedence, they are processed right-to-left, so A = B = 0 is processed as A = (B = 0) (B = 0 returns 0, so both A and B end up as 0).
Equality operators like == are left-associative: same-precedence operators are processed left-to-right. A == B == 0 is processed as (A == B) == 0, and since A == B is true (1), it becomes 1 == 0, which is false (0).
Likewise, A == B == 1 is processed as (A == B) == 1, which becomes 1 == 1, which is true (1).
Source and more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
First, A == B returns true, which is then compared to 0, true == 0 which returns false, or true == 1 which returns true.
It first checks your clause for A == B, which is true, than it starts checking true == 0, and 0 is false. So when you check A == B == 1, you check A==B, which is true, and true == 1. So then it returns true. If you really want to check all possibilities you should do something like this:
if((A==B) && (A==0))
console.log(true);
else
console.log(false);
if((A == B)&& (A== 0)&& (B==0))
console.log(true);
else
console.log(false);
You can work from left to right. In this case you first check if A == B, then you check if this equal to 0. So since A == B, this is true. So now it becomes (true == 0), which is false. If A=1, B=2, then (A == B == 0) would return true! This is because A == B is false and (false == 0) is true!

Javascript chained inequality gives bizarre results [duplicate]

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.

Categories

Resources