Why my condition is always true - javascript

I would like to know in this example why my condition is always true ? Thanks
function bla() {
var qix = 'z'
if (qix === 'a' || 'b' || 'c') {
console.log('condition ok!! whats wrong???')
}
}

The problem with your code is that the if expression always evaluates to true.
qix === 'a' || 'b' || 'c'
will actually become this:
false || 'b' || 'c'
as qix is set to z. Due to loose typing, JavaScript returns true for the second expression because 'b' is a truthy value. To correct that, you need to change the expression as follows:
qix === 'a' || qix === 'b' || qix === 'c'
so that it correctly means what you're expecting.

Description of expr1 || expr2 from MDN:
Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true.
o1 = true || true // t || t returns true
o2 = false || true // f || t returns true
o3 = true || false // t || f returns true
o4 = false || (3 == 4) // f || f returns false
o5 = 'Cat' || 'Dog' // t || t returns "Cat"
o6 = false || 'Cat' // f || t returns "Cat"
o7 = 'Cat' || false // t || f returns "Cat"
o8 = '' || false // f || f returns false
o9 = false || '' // f || f returns ""
So this expression from your code, assuming qix is not 'a':
qix === 'a' || 'b' || 'c'
The first term qux === 'a' is false, which of course evaluates to false. This causes it to go to the next term which is 'b'. Non-empty strings evaluate to true, so it stops there and just becomes 'b'. Now your if statement can be thought of as just:
if ('b')
Again, 'b' evaluates to true. So your conditional is effectively doing nothing.

I think you are missing two concepts.
First how the || operator works and second coercion of javascript values.
In your code:
if ('z' === 'a' || 'b' || 'c') { ----}
Will always evaluate to true.
The reason for this is that the || operator will give back the first value which coerces to true without actually coercing the value. The associativity (order which the operators are executed) is left-to-right. This means that the following happens:
First the following will be evaluated because it has higher precedence:
'z' === 'a' // false
then we have the following expression which will be evaluated left to right:
false || 'b' || 'c'
let foo = false || 'b'
console.log(foo)
Then we have the following expression:
let foo = 'b' || 'c'
console.log(foo)
So the whole expression evulates to the string 'b'
After the expression inside the if statement is evaluated to the value 'b' this in turn then gets coerced into a boolean. Every string gets converted to true and that's why the value is always true.

This is because you 'if condition' is take 3 possible option
First say qix === 'a', this is false but you asking about 'b','c' and this option are values true because you are not compare var qix with 'b' or 'c', you only asking to IF condition, that if 'b' or 'c' are value
the operator || it is used so
if(First Condition || Second Condition || third condition){
if at least one of these options is true, then enter here
}
In ECMAScript 2016 incorporates an includes() method for arrays that specifically solves the answer
if (['b', 'c', 'a'].includes(qix)) {
this is false
}
if (['z', 'c', 'a'].includes(qix)) {
this is true
}
Or you can write so
function bla() {
var qix = 'z'
if (qix === 'a' || qix === 'b' || qix === 'c') {
console.log('condition ok!! whats wrong???')
}
}

As we know || (OR Logical Operators) returns true if either operand is true. In your if condition qix === 'a' || 'b' || 'c' in their second and third operand is string and Strings are considered false if and only if they are empty otherwise true. For this reason, your condition is always true.
Need to check qix like qix ==='b'
var qix = 'z'
if (qix === 'a' || qix === 'b' || qix ==='c') {
console.log('condition ok!! whats wrong???')
}
else{
console.log('else')
}

You could use Regex: qix.match(/^(a|b|c)$/)
Should return if qix is equals to a or b or c
var qix = 'z';
if (qix.match(/^(a|b|c)$/)) {
console.log('condition ok!! whats wrong???');
} else {
console.log('else');
}

JavaScript returns true for the second or expression because 'b' is always true.
You need to check each value against qix like so:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
var qix = 'z'
if (qix === 'a' || qix === 'b' || qix === 'c') {
console.log('condition ok!! whats wrong???')
}

Related

Why ternary expression is executed after falsy value in Javascript?

As far as I know expressions are not executed after falsy values in Javascript. For example in the following statement:
const result = undefined && 5;
console.log(result);
result will be undefined.
However:
const result = false && false ? 'T' : 'F';
console.log(result);
result will be equal to F. Why is the ternary expression still executed?
This is because of operator precedence: && has higher precedence (6) than ? : (4), so
false && false ? 'T' : 'F'
evaluates to
(false && false) ? 'T' : 'F'
So, the left-hand side evaluates to false first (taking the first false), and then goes on to the conditional operator.
If you had put parentheses after the &&, result would be false, as you're expecting:
const result = false && (false ? 'T' : 'F');
console.log(result);
const result = false && false ? 'T' : 'F'
As we know ternary expression is a short form of IF else condition,the above statement is like
if(false && false){
return 'T'
}else{
return 'F'
}
So result value we getting as "F"

Why '=' and '||' will be evaluated to be true?

I read this post, it mentioned this if (variable == 1 || 2 || 6) cannot work (JS Short for if (a == b || a == c)).
But I tried this example, it will be evalauted to be true, why?
var a = 'apple';
if('apple2' == a || 'banana' ) {
alert('hi');
}
Here is the working example:
https://jsfiddle.net/Loun1ggj/
Update:
if('apple2' == a || 'banana' ) is not evaluated into if('apple2 == a' || 'apple' == 'banana')?
Let's break down the expression:
if('apple2' == a || 'banana' )
The first part to be evaluated is the ==, because it has highest operator precedence:
'apple2' == a
This is a standard equality, and returns false, giving us:
if(false || 'banana')
The || operator in JS returns not true or false, but whichever of its arguments is "truthy". A non-empty string like 'banana' is considered "truthy", so we end up with this:
if('banana')
Now we again look at the "truthiness" of 'banana', and the if statement proceeds.
Since 'banana' is always true, it would always run, see the below example
var a = 'apple';
if('apple2' == a) {
alert('hi');
}
if('banana'){
alert('hello');
}
if('apple2' == a || 'banana' ) is evaluated this way:
if(('apple2' == a) || ('banana') ), which is:
if :
'apple2' == a // false
||(or)
'banana' // true, since Boolean('banana') is true (a non-empty string is a truthy value)
so => if (false or 'banana') => if ('banana') // => true
It's not evaluated as if('apple2' == a || 'apple2' == 'banana' ).
According to this, the operator == has higher precedence over operator ||. So the expression is evaluated as follows:
if('apple2' == a || 'banana' )
'apple2' == a //false
'banana' //true (non-empty string)
So final evaluation will be, always true:
if(false || true) //true
There's 2 expressions here
'apple2' == a which resolve to falsy
'banana' which resolve to thruthy
Because 'banana' is not undefined or null essentially.

Having trouble with an if/else statement

I'm trying to write a function called isVowel that takes a character (i.e. a string of length 1) and returns "true" if it is a vowel, uppercase or lowercase. The function should return "false" if the character is not a vowel.
This seems like it should work, but no matter what letter I enter, it returns "true." I've tried a bunch of different things, but I've hit a wall.
function isVowel(x){
if (x === "a" || "A" || "e" || "E" || "i" || "I"|| "o" || "O" || "u" || "U" || "y" || "Y"){
//console.log(x); // returns c
return true
} else {
return false
}
};
console.log(isVowel("c"));
To simplify your code even further, you can create an array of valid values and simply check if the value they passed in is contained in the valid values list.
function isVowel(x) {
var vowels = ["a", "e", "i", "o", "u", "y"];
return vowels.indexOf(x.toLowerCase()) > -1;
};
console.log(isVowel("a"));
Below is the improved and corrected version of your function:
Instead of checking all conditions for capital and small we first conver to small and then check using x == a/e/i/o/u.
function isVowel(x)
{
x = x.toLowerCase();
if (x === "a" || x == "e" || x == "i" || x == "o" || x == "u"){
return true
} else {
return false
}
};
console.log(isVowel("a"));
A better approach suggested by #yBrodsky is:
function isVowel(x)
{
var vowels = ['a', 'e', 'i', 'o', 'u'];
return vowels.indexOf(x.toLowerCase()) != -1;
};
console.log(isVowel("a"));
You can use /[a|e|i|o|u]/i.test(YOURTEXTHERE).
Below is a single liner to accomplish this:
var YOURTEXTHERE = 'b';
// check if it's vowel
if (/[a|e|i|o|u]/i.test(YOURTEXTHERE)) {
console.log('vowel!');
}
else
console.log('not vowel');
Your use of the || operator is incorrect. Your code is currently evaluating x === "a", then "A" which is always a truthy value. You either need to use a list of comparisons like this:
if (x === "a" || x === "A" || x === "o" || ...) {...}
Or something like this (much neater, and faster):
if (['a', 'e', 'i', 'o', 'u'].indexOf(x.toLowerCase())) {...}
You are only comparing x == "a", you need to have
x=="A"||x=="o" and so on.
A clean version might be:
function isVowel(x) {
return (['a', 'e', 'i', 'o', 'u', 'y'].indexOf(x.toLowerCase()) > -1);
};
console.log(isVowel("c"));
console.log(isVowel("a"));
console.log(isVowel("A"));
As you're passing in a string with a length of 1 you could use String.includes for a simple comparison. No need for any arrays at all.
function isVowel(x){
return 'aeiouy'.includes( x.toLowerCase() );
};
console.log( isVowel("c") ); // false
console.log( isVowel("e") ); // true
Perhaps a different approach and a cleaner solution may work better as follows.
function isVowel(character) {
// Clean the character to eliminate errors with capital letters
let cleanedChar = character.toLowerCase();
// Check if the cleaned character which is now any lower case letter matches a vowel
if (cleanedChar.match(/[aeiou]/g)) {
// Return true if it does
return true;
}
// return false if ever get to this point (it means the char was not a vowel)
return false;
}
// Call isVowel function and pass it 'c'
console.log(isVowel('c'));

Javascript Logical Operator:?

I was examining the src of underscore.js and discovered this:
_.isRegExp = function(obj) {
return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
};
Why was "!!" used? Should it be read as NOT-NOT or is there some esoteric JS nuance going on here?
It is just an obtuse way to cast the result to a boolean.
Yes, it's NOT-NOT. It is commonly used idiom to convert a value to a boolean of equivalent truthiness.
JavaScript understands 0.0, '', null, undefined and false as falsy, and any other value (including, obviously, true) as truthy. This idiom converts all the former ones into boolean false, and all the latter ones into boolean true.
In this particular case,
a && b
will return b if both a and b are truthy;
!!(a && b)
will return true if both a and b are truthy.
The && operator returns either false or the last value in the expression:
("a" && "b") == "b"
The || operator returns the first value that evaluates to true
("a" || "b") == "a"
The ! operator returns a boolean
!"a" == false
So if you want to convert a variable to a boolean you can use !!
var myVar = "a"
!!myVar == true
myVar = undefined
!!myVar == false
etc.
It is just two ! operators next to each other. But a double-negation is pointless unless you are using !! like an operator to convert to Boolean type.
It will convert anything to true or false...

JavaScript equality transitivity is weird

I've been reading Douglas Crockford's JavaScript: The Good Parts, and I came across this weird example that doesn't make sense to me:
'' == '0' // false
0 == '' // true
0 == '0' // true
false == undefined // false
false == null // false
null == undefined // true
The author also goes on to mention "to never use == and !=. Instead, always use === and !==". However, he doesn't explain why the above behavior is exhibited? So my question is, why are the above results as they are? Isn't transitivity considered in JavaScript?
'' == '0' // false
The left hand side is an empty string, and the right hand side is a string with one character. They are false because it is making a comparison between two un identical strings (thanks Niall).
0 == '' // true
Hence, why this one is true, because 0 is falsy and the empty string is falsy.
0 == '0' // true
This one is a bit trickier. The spec states that if the operands are a string and a number, then coerce the string to number. '0' becomes 0. Thanks smfoote.
false == undefined // false
The value undefined is special in JavaScript and is not equal to anything else except null. However, it is falsy.
false == null // false
Again, null is special. It is only equal to undefined. It is also falsy.
null == undefined // true
null and undefined are similar, but not the same. null means nothing, whilst undefined is the value for a variable not set or not existing. It would kind of make sense that their values would be considered equal.
If you want to be really confused, check this...
'\n\r\t' == 0
A string consisting only of whitespace is considered equal to 0.
Douglas Crockford makes a lot of recommendations, but you don't have to take them as gospel. :)
T.J. Crowder makes an excellent suggestion of studying the ECMAScript Language Specification to know the whole story behind these equality tests.
Further Reading?
The spec.
yolpo (on falsy values)
The answer to this question has to do with how JavaScript handles coercion. In the case of ==, strings are coerced to be numbers. Therefore:
'' == '0' is equivalent to '' === '0' (both are strings, so no coercion is necessary).
0 == '' is equivalent to 0 === 0 because the string '' becomes the number 0 (math.abs('') === 0).
0 == '0' is equivalent to 0 === 0 for the same reason.
false == undefined is equivalent to 0 === undefined because JavaScript coerces booleans to be numbers when types don't match
false == null is equivalent to 0 === null for the same reason.
null == undefined is true because the spec says so.
Thanks for asking this question. My understanding of == is much better for having researched it.
You can actually write a JavaScript function that behaves exactly like == that should give you some insight into how it behaves.
To show you what I mean here is that function:
// loseEqual() behaves just like `==`
function loseEqual(x, y) {
// notice the function only uses "strict" operators
// like `===` and `!==` to do comparisons
if(typeof y === typeof x) return y === x;
if(typeof y === "function" || typeof x === "function") return false;
// treat null and undefined the same
var xIsNothing = (y === undefined) || (y === null);
var yIsNothing = (x === undefined) || (x === null);
if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);
if(typeof x === "object") x = toPrimitive(x);
if(typeof y === "object") y = toPrimitive(y);
if(typeof y === typeof x) return y === x;
// convert x and y into numbers if they are not already use the "+" trick
if(typeof x !== "number") x = +x;
if(typeof y !== "number") y = +y;
return x === y;
}
function toPrimitive(obj) {
var value = obj.valueOf();
if(obj !== value) return value;
return obj.toString();
}
As you can see == has a lot of complicated logic for type conversion. Because of that it's hard to predict what result you are going to get.
Here are some examples of some results you wouldn't expect:
Unexpected Truths
[1] == true // returns true
'0' == false // returns true
[] == false // returns true
[[]] == false // returns true
[0] == false // returns true
'\r\n\t' == 0 // returns true
Unexpected Conclusions
// IF an empty string '' is equal to the number zero (0)
'' == 0 // return true
// AND the string zero '0' is equal to the number zero (0)
'0' == 0 // return true
// THEN an empty string must be equal to the string zero '0'
'' == '0' // returns **FALSE**
Objects with Special Functions
// Below are examples of objects that
// implement `valueOf()` and `toString()`
var objTest = {
toString: function() {
return "test";
}
};
var obj100 = {
valueOf: function() {
return 100;
}
};
var objTest100 = {
toString: function() {
return "test";
},
valueOf: function() {
return 100;
}
};
objTest == "test" // returns true
obj100 == 100 // returns true
objTest100 == 100 // returns true
objTest100 == "test" // returns **FALSE**

Categories

Resources