Make positive numbers evaluate to true and negative to false - javascript

I'm playing around in javascript and I am wondering if you could make all
values greater than -1 evaluate to true and all values from -1 and down evaluate to false?
Right now 1 == true and everything else equals false if you write it like this:
var i = 0;
if (i) {...} // I want this to be true
i = 1;
if (i) {...} // This is the only thing that is true
EDIT: With evaluate I mean that I don't runt a comparison, e.g. 0 > -1.
I want JavaScript to coerce the number into a boolean value.

you mean this?
if ( i > -1 ) {
....
}

No, you can't change that, because it's built into the way the JavaScript == operator coerces values between types.
If you have a loose equality expression (==) where one of the operands is a boolean (true or false) and the other is a number, the JavaScript engine will try to convert the boolean into a number and will compare the result. true converts to 1 if you try to convert it to a number, and so that's why 1 == true.

Related

Can any one explain me how does the string and number comparison work in javascript?

I have compared some strings and numbers to see the result as true and false
"dfdf" > 1
false
"dfdf" > 99
false
"dfdf" > 9999
false
"dfdf" > 99999
false
1> ''
true
1> '545'
false
1> '545d'
false
1> '555'
false
1> 'ddfdf'
false
9999 > 'dfsdfadf'
false
I have tried few different combinations in the code as you can see but got the mixed result and want to know how exactly the comparison works in javascript.
another addition which is even more confusing
"dasfads" > "dasfdsf"
false
"abc" > "a"
true
"abc" > "agf"
false
"abcf" > "agf"
false
Comparing a string to a number will force the string data to evaluate into a number value. If the string data is not convertible to a numerical value it will return a NaN number to the given comparison.
Since NaN is not comparable nor equal to anything at all, not even to another NaN
NaN == NaN > false
The 'greater than' or 'smaller than' NaN comparison will have to return false both ways. Because that's the only correct answer, nothing can be greater nor smaller than the value you don't have. Therefore both claims are false. e.g.: 0 > NaN and 0 < NaN > false.
But keep in mind that comparing two strings of data such as:
"98A" > "999" will return a comparative false,
whereas:
"9A" > "999" will return true
Which is a very powerful thing to know, because knowing this (two strings will be compared by alphabetical order of magnitude) you are able to compare time data without taking the burden of converting those values to numbers and directly go with:
"09:32:28" > "09:31:59" > true
And luckily "PM" > "AM" > true by pure (linguistic) chance.
It is attempting to cast the string to a number.
In the console, if you do
x = +''
then x will be set to 0. 1 > 0 is true.
For all the other ones, if you do something like
x = +'dfdf'
then x will be set to NaN (not a number), and any comparison with it will return false.
There are 2 types of comparison available when using JavaScript,
The standard equality operators (== and !=) use the Abstract Equality Comparison Algorithm to compare two operands. If the operands are of different types, it will attempt to convert them to the same type before making the comparison, e.g., in the expression 5 == '5', the string on the right is converted to Number before the comparison is made.
The strict equality operators (=== and !==) use the Strict Equality Comparison Algorithm and are intended for performing equality comparisons on operands of the same type. If the operands are of different types, the result is always false so 5 !== '5'.
So if you want to know what is happening there, JavaScript is trying to convert the string into a Number and then do comparison, however, since they are not a number, which is always converted to NaN, and comparison with NaN will be equal to false.
Link for details:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators
String Vs String
The comparison is done character by character when you are comparing strings. First different character found in both string will be compared using their char codes. (Note: Chars after that will be ignored.)
>> "a".charCodeAt(0)
97
>> "}".charCodeAt(0)
125
>> "}" > "a"
true
>> "-}" > "a"
false
String Vs Number
Any time a string is compared with a number the string is converted into an integer and then both are compared. If the string can't be converted into a number, then it returns false. (Note: NaN, Nothing can be compared against NaN. Any comparison with NaN will return false)
>> 'dfsdfadf' > 999999 // Can't be converted to integer, hence false
false
>> 'd' > 9999999999 // Can't be converted to integer, hence false
false
>> '' == false // '' is empty string which is 0 or false
true
>> 1 > '' // '' is false,0 explained in prev case
true

What is happening in this loose equality comparison of 2 empty arrays

I am struggling with understanding how this snippet works on a basic level
if([] == ![]){
console.log("this evaluates to true");
}
Please help me understand where I got it wrong. My thinking:
First there is operator precedence so ! evaluates before ==.
Next ToPrimitive is called and [] converts to empty string.
! operator notices that it needs to convert "" into boolean so it takes that value and makes it into false then negates into true.
== prefers to compare numbers so in my thinking true makes 1 and [] is converted into "" and then 0
Why does it work then? Where did I get it wrong?
Why does it work then?
TLDR:
[] == ![]
//toBoolean [1]
[] == !true
[] == false
//loose equality round one [2]
//toPrimitive([]); toNumber(false) [3]
"" == 0
//loose equality round two
//toNumber("") [4]
0 === 0
true
Some explanations:
1)
First there is operator precedence so ! evaluates before ==
Negating something calls the internal toBoolean method onto that "something" first. In this case this is an Object (as Arrays are Objects) and for that it always returns true which is then negated.
2)
Now it's up to loose equalities special behaviour ( see Taurus answer for more info) :
If A is an Object ( Arrays are Objects ) and B is a Boolean it will do:
ToPrimitive(A) == ToNumber(B)
3)
toPrimitive([])
ToPrimitive(A) attempts to convert its Object argument to a primitive value, by attempting to invoke varying sequences of A.toString and A.valueOf methods on A.
Converting an Array to its primitive is done by calling toString ( as they don't have a valueOf method) which is basically join(",").
toNumber(false)
The result is 1 if the argument is true. The result is +0 if the argument is false. Reference
So false is converted to +0
4)
toNumber("")
A StringNumericLiteral that is empty or contains only white space is converted to +0.
So finally "" is converted to +0
Where did I get it wrong?
At step 1. Negating something does not call toPrimitive but toBoolean ...
The accepted answer is not correct (it is now, though), see this example:
if([5] == true) {
console.log("hello");
}
If everything is indeed processed as the accepted answer states, then [5] == true should have evaluated to true as the array [5] will be converted to its string counterpart ("5"), and the string "5" is truthy (Boolean("5") === true is true), so true == true must be true.
But this is clearly not the case because the conditional does not evaluate to true.
So, what's actually happening is:
1. ![] will convert its operand to a boolean and then flip that boolean value, every object is truthy, so ![] is going to evaluate to false.
At this point, the comparison becomes [] == false
2. What gets into play then is these 2 rules, clearly stated in #6 in the specs for the Abstract Equality Comparison algorithm:
If Type(x) is boolean, return the result of the comparison ToNumber(x) == y.
If Type(y) is boolean, return the result of the comparison x == ToNumber(y)
At this point, the comparison becomes [] == 0.
3. Then, it is this rule:
If Type(x) is Object and Type(y) is either String or Number,
return the result of the comparison ToPrimitive(x) == y.
As #Jonas_W stated, an array's ToPrimitive will call its toString, which will return a comma-separated list of its contents (I am oversimplifying).
At this point, the comparison becomes "" == 0.
4. And finally (well, almost), this rule:
If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.
An empty string converted to a number is 0 (Number("") == 0 is true).
At this point, the comparison becomes 0 == 0.
5. At last, this rule will apply:
If Type(x) is the same as Type(y), then
.........
If Type(x) is Number, then
.........
If x is the same Number value as y, return true.
And, this is why the comparison evaluates to true. You can also apply these rules to my first example to see why it doesn't evaluate to true.
All the rules I quoted above are clearly stated here in the specs.
First, realize that you are comparing two different types of values.
When you use ![] it results in false. You have code (at core it results in this):
if([] == false)
Now the second part: since both values are of different type and you are using "==", javascript converts both value type into string (to make sure that they have same type). It starts from left.
On the left we have []. So javascript applies the toString function on [], which results in false. Try console.log([].toString())
You should get false on the left as string value. On the right we have boolean value false, and javascript does the same thing with it.
It use the toString function on false as well, which results in string value false.
Try console.log(false.toString())
This involves two core concepts: how "==" works and associativity of "==" operator - whether it starts from left or right.
Associativity refers to what operator function gets called in: left-to-right or right-to-left.
Operators like == or ! or + are functions that use prefix notation!
The above if statement will result in false if you use "===".
I hope that helps.

Why does this set of logical operators work correctly?

So I'm doing a puzzle to evaluate Kaprekar's Routine and in the first section I need to check to make sure the 4 digit input has at least two unique digits so I did this:
let numArr = num.toString().split("");
if (numArr[0] == numArr[1] && numArr[2] && numArr[3]) {
return 0;
}
I tried searching but I keep finding links to short-circuiting operators. I was expecting to write out numArr[0] == into every && block but to my surprise it worked. Can anyone explain why this returns 0 for 3333 but does not for 1234? I assumed numArr[2] and numArr[3] would just evaluate to true automatically.
There is a thing called operator precedence. The operator with higher precedence happens first. == happens before &&. When you have more than one operator of the same precedence it goes by 'associativity' which is generally left to right (= for example is right to left); so let's take another look at your code
if ( ((numArr[0] == numArr[1]) && numArr[2]) && numArr[3] )
Let's take just the first piece. Doing 3 == 3 is true and since none of the operators are 0, the if statement is true. But with 1234, 1 == 2 is false, so the expression short circuits to false. Generally when something (like an if statement) accepts a boolean value && a non zero/undefined/false value, the expression is considered true (I may be wrong). If you do the below you should get true
if ( numArr[0] && numArr[1] && numArr[2] && numArr[3] )
To answer your other question, generally when people work with a set of data in JS they use lodash. You can find the if there is 2 unique values easily with the line blow. uniq(array, func) returns an array with unique values in the same order. See the documentation
_.uniq("3333".toString().split(""), v=>v).length >= 2 //false
_.uniq("1224".toString().split(""), v=>v).length >= 2 //true
It is because
For String 3333
num[0] is 3,num[1]=3,num[2]=3,num[3]=3
Expressions evaluate based on precedence of operators
and when the operators have the same precedence they get executed from left to right
In this case == has highest precedence over &&
so,
num[0]==num[1] ,it is 3==3 true
then
true && num[2] && num[3] => true&&3&&3 => true
For string 1234
num[0]=1,num[1]=2,num[2]=3,num[3]=4
num[0]==num[1] ,1==2 is false
so now the expression is
false && num[2] && num[3]
For && operator if the first operand is false,it ignore the rest of the expression
so now it just results as false
Hope this helps
You have three expressions being evaluated
// loose-equality, so true if after type-coersion, the values are equivalent
// this is the only condition that is actually changing in your code, unless
// you have a number with less than 4 digits
numArr[0] == numArr[1]
// is a non-empty string so it's 'truthy'
numArr[2]
// is a non-empty string so it's 'truthy'
numArr[3]
Anything that is not Falsy (false, 0, "", null, undefined, and NaN) is Truthy
Therefore, you need to write additional code to check for unique digits.

Why if([]) is validated while [] == false in javascript?

if([] == false) alert('empty array is false');
alert(+[]) // alert 0
if([]) alert('empty array is true');
They both will run the alert
Demo
Both current answers here are correct, but I'd like to add a more detalied explanation based on the language specification. The reason for the apparently contradictory outcomes is that if statements and equality comparisons are evaluated differently.
In the case of an if(expression) statement, the expression is evaluated and then converted to the boolean type (§ 12.5). Arrays are Objects, and when an Object is converted to Boolean, the result is always true (§ 9.2).
Equality comparisons with == follow a different set of rules, detailed on § 11.9.3. The comparison may require multiple type conversions, until both operands are the same type. The order of the operands is also important. According to that algorithm, we can see that the comparison [] == false is actually a four-step operation:
There is a Boolean involved, so it's converted to a Number first (step 7 of the algorithm). So it becomes:
[] == 0
Then the array is converted to its primitive value (see § 9.1 and § 8.12.8), and becomes an empty string (step 9). So:
"" == 0
When comparing a String to a Number, the String is converted to Number first (step 5, following the rules described on § 9.3.1):
0 == 0
Now that we have two Numbers, the comparison evaluates to true according to step 1.c.iii.
It's because of type coercion of the == (equality) operator.
An empty array is considered truthy (just like an empty object), thus the second alert is called.
However, if you use ([] == false), your array is coerced to its string representation* which is "" which then is considered as a falsy value, which makes the condition true thus triggering the first alert too.
If you want to avoid type coercion, you have to use the === (identity) operator which is the preferred and by the famous Douglas Crockford promoted way to compare in javascript.
You can read more on that matter in this exhaustive answer.
*(Object.prototype.toString is called on it)
EDIT:
fun with JS-comparison:
NaN == false // false
NaN == true // also false
NaN == NaN // false
if(NaN) // false
if(!NaN) // true
0 == '0' // true
'' == 0 // true
'' == '0' // false !
This shows you the real "power" of Comparison with == due to the strange rules mentioned in bfavarettos answer.
There is a difference between evaluating a value as a boolean, and comparing it to true or false.
Whe using the == operator, the values are converted so that the types correspond. The [] value converted to the empty string "", and converting that in turn to a boolean gives false, so [] == false becomes true.
Evaluating [] as a boolean value will return true, because it is not a 'falsy' value, i.e. 0, false, null, "", NaN or undefined.

Why do alert(!!"0") and alert(false == "0") both output true in JavaScript

As far as I know in JavaScript !! is supposed to normalize a boolean value converting it to true or false from some other type. This would mean that the "0" converts to boolean true. On the other hand if I compare it with false it turns out that it is in fact false (as the result of the comparison is true). What rule am I missing here. I have tested it in IE and Opera.
The == operator checks for loose equality, which has nothing to do with truthiness.
Specifically, it will convert to operands to numbers, then compare the numbers.
Strings containing numbers convert to the numbers that they contain; booleans convert to 0 and 1.
Objects are converted by calling valueOf, if defined.
Thus, all of the following are true:
"1" == 1
"0" == false
"1" == true
"2" != true
"2" != false
({ valueOf:function() { return 2; } }) == 2
({ valueOf:function() { return 1; } }) == true
In the first case, a non-empty string is equivalent to true.
In the second case, because one operand is a boolean, both operands are converted to numeric values. I believe false converts to the numeric value 0 and the string "0" also converts to a numeric 0, resulting in 0 == 0 which is true.
Check out the Mozilla reference for operator behavior.
For the first expression, section 9.2 of ECMA-262 defines an abstract operation ToBoolean internally used by the logical NOT operator. It says:
String
The result is false if the argument is the empty String (its length is zero); otherwise the result is true.
For the second expression, JavaScript will perform type coercion when it attempts to compare these values of different data types. Douglas Crockford says that this is a misfeature. It would be false if you had used === instead of ==. The rules are rather complex, so you should directly look in section 11.9.3 of ECMA-262 for the details.

Categories