Javascript logical operators: multiple || syntax dilemma - javascript

var choice1 = prompt("Enter choice 1");
var choice2 = prompt("Enter choice 2");
if (choice1 === "x" && choice2 === ("a" || "b" || "c")) {
alert("Good job!");
}
Assume the user input x for choice1 and c for choice 2.
The above is a simple example to highlight my issue. I know it doesn't work but my question is why? Javascript won't compare the multiple || statements within () against choice2. Why not? The logic in my mind is choice2 is the same type and value (===) as "a" or "b" or "c".
The way I got it working was this:
(choice1 === "x" && ((choice2 === "a") || (choice2 === "b") || (choice3 === "c"));
Please help me understand why when using multiple ||'s, you need to explicitly write out each || scenario as opposed to putting a bunch within () as I tried up top. Thanks.

It just doesn't work that way, you can't compare one value against multiple other values using OR, you have to compare each value individually.
The closest you'll get is using Array.indexOf
if ( ['a', 'b', 'c'].indexOf(choice2) != -1 )
The reason it doesn't work is because OR and AND checks for a truthy value, so in
('a' || 'b' || 'c') // return "a"
a is a truthy value, so the OR never proceeds, it doesn't have to, it already has a truthy value so the expression is true, and you're left with a, the rest is discarded

In JavaScript, if you do this
var a = null;
var b = {};
var c = "haha"
var d = a || b || c;
the value of d will be b. Expressions of type var1 || var2 || var3 return with the value of first not null or not undefined value.
So, in you case choice2 === ("a" || "b" || "c") is same as writing choice2 === "a".

(object || object) syntax is something like null check operator not for condition check in javascript.
so
console.log(null || "b") would log b
console.log(undefined || "b") would log b
console.log(("a" || "b")) would log a
console.log(null || "b")
console.log(undefined || "b")
console.log(("a" || "b"))
Your condintion(below) will only work if choice2 is "a" and choice1 is "x".
if (choice1 === "x" && choice2 === ("a" || "b" || "c")) {
alert("Good job!");
}

What is in the brackets get evaluated first so ("a" || "b" || "c") will evaluate to "a" because what you are effectively saying is return either "a" or "b" or "c" so it returns "a" because that is first.
I believe what you are expecting is ("a" || "b" || "c") to act some sort of set operation but JavaScript doesn't have that feature so your code choice2 === ("a" || "b" || "c") will only ever be true if the user chose "a". The best way to compare multiple values with choice2 is to store "a","b" and "c" in an array and see if choice2 exists in it. ["a","b","c"].indexOf(choice2) != -1.
In most languages you won't even be able to compare three strings but JavaScript does everything it can to not throw exceptions so it doesn't cause the user of the website to realise there is a problem with the page so it will try and compare the three strings as you would compare three booleans but instead of returning a boolean it returns a string. I would avoid that syntax completely as it would confuse most developers not familiar with the weird ways of JavaScript.

Related

How to check if variable is not falsy but 0 passes in Javascript

Is there an elegant way to check if variable is NOT falsy but in case of 0 it passes. The issue with this way of verifying
if(var !== undefined && var !== null)
is that it's long and doesn't cover all cases like undecalred or NaN. I'm also using typescript and declare it as optional number.
You can do exactly what your first sentence asks:
if (!x && x !== 0)
means literally "if x is falsy and x is not 0".
Also the == and != comparison operators explicitly consider null and undefined to be equal, so
if (x != null)
is true for both null and undefined. (That's !=, not !==.)
function Check(input) {
if (!input && input!==0){
return "falsy";
}
else if (input === 0){
return "zero";
}
}
console.log(Check(0));
console.log(Check(false))

If keydown !== A,B or C in Javascript? [duplicate]

I want to write an if/else statement that tests if the value of a text input does NOT equal either one of two different values. Like this (excuse my pseudo-English code):
var test = $("#test").val();
if (test does not equal A or B){
do stuff;
}
else {
do other stuff;
}
How do I write the condition for the if statement on line 2?
Think of ! (negation operator) as "not", || (boolean-or operator) as "or" and && (boolean-and operator) as "and". See Operators and Operator Precedence.
Thus:
if(!(a || b)) {
// means neither a nor b
}
However, using De Morgan's Law, it could be written as:
if(!a && !b) {
// is not a and is not b
}
a and b above can be any expression (such as test == 'B' or whatever it needs to be).
Once again, if test == 'A' and test == 'B', are the expressions, note the expansion of the 1st form:
// if(!(a || b))
if(!((test == 'A') || (test == 'B')))
// or more simply, removing the inner parenthesis as
// || and && have a lower precedence than comparison and negation operators
if(!(test == 'A' || test == 'B'))
// and using DeMorgan's, we can turn this into
// this is the same as substituting into if(!a && !b)
if(!(test == 'A') && !(test == 'B'))
// and this can be simplified as !(x == y) is the same as (x != y)
if(test != 'A' && test != 'B')
ECMA2016 answer, especially good when checking against multiple values:
if (!["A","B", ...].includes(test)) {}
In general it would be something like this:
if(test != "A" && test != "B")
You should probably read up on JavaScript logical operators.
I do that using jQuery
if ( 0 > $.inArray( test, [a,b] ) ) { ... }
For a larger number of values that is checked against often, it may be more efficient to check if the value does not exist in a Set.
const values = new Set(["a", "b"]);
if(!values.has(someValue)){
// do something
} else {
// do something else
}
var test = $("#test").val();
if (test != 'A' && test != 'B'){
do stuff;
}
else {
do other stuff;
}
You used the word "or" in your pseudo code, but based on your first sentence, I think you mean and. There was some confusion about this because that is not how people usually speak.
You want:
var test = $("#test").val();
if (test !== 'A' && test !== 'B'){
do stuff;
}
else {
do other stuff;
}
This can be done with a switch statement as well. The order of the conditional is reversed but this really doesn't make a difference (and it's slightly simpler anyways).
switch(test) {
case A:
case B:
do other stuff;
break;
default:
do stuff;
}

A way to combine multiple if statements all to one line with some clever spacing

I want to find a way to combine multiple if statements all to one line with some clever spacing.
var myBool = myObject.prop1 ||
myObject.prop2 &&
myObject.prop3.someproperty
Since prop3 might be empty so I want to check if "someproperty" exist in prop3.
But I do not want to add another if statement like
typeof myObject.prop3.someproperty === 'undefined before my myBool.
Is there anyway that I can make everything in one line with clever spacing?
var myBool = Boolean(myObject.prop1 ||
myObject.prop2 &&
myObject.prop3 && myObject.prop3.someproperty);
or
var myBool = !!(myObject.prop1 ||
myObject.prop2 &&
myObject.prop3 && myObject.prop3.someproperty);
since your naming implies that you expect myBool to contain a real boolean, not some truthy or falsy value
var myBool = myObject.prop1 ||
myObject.prop2 &&
myObject.prop3.someproperty != null
? myObject.prop3.someproperty
: false

Javascript symbol about "if" statement

I got an "if" statement and i want to check if one textcontent of the variable is different from A or from B
but this doesnt seem to work
Any suggestion ??
if ( el[0].textContent != "A" || "B")
if ( el[0].textContent != "A" || el[0].textContent != "B")
if ( el[0].textContent != "A" && el[0].textContent != "B")
2nd solution from Phil_1984_
Check this out.
You have to declare to your variable both of the "things" you need to check.
and after this you will have the result you want.

Why is the following true: "Dog" === ("Cat" && "Dog")

Why does the && operator return the last value (if the statement is true)?
("Dog" == ("Cat" || "Dog")) // false
("Dog" == (false || "Dog")) // true
("Dog" == ("Cat" && "Dog")) // true
("Cat" && true) // true
(false && "Dog") // false
("Cat" && "Dog") // Dog
("Cat" && "Dog" && true) // true
(false && "Dog" && true) // false
("Cat" && "Dog" || false); // Dog
Fiddle
Logical Operators - && (MDN)
Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both
operands are true; otherwise, returns false.
For your expression "Cat" && "Dog" , the first expression "Cat" can't be converted to false or a boolean value, hence it returns "Dog"
Think of && in JavaScript like this (based on ToBool from the es5 spec)
function ToBool(x) {
if (x !== undefined)
if (x !== null)
if (x !== false)
if (x !== 0)
if (x === x) // not is NaN
if (x !== '')
return true;
return false;
}
// pseudo-JavaScript
function &&(lhs, rhs) { // lhs && rhs
if (ToBool(lhs)) return rhs;
return lhs;
}
Now you can see that ToBool("Cat") is true so && will give rhs which is "Dog", then === is doing "Dog" === "Dog", which means the line gives true.
For completeness, the || operator can be thought of as
// pseudo-JavaScript
function ||(lhs, rhs) { // lhs || rhs
if (ToBool(lhs)) return lhs;
return rhs;
}
Why does the && operator return the last value?
Because that's what it does. In other languages, the && operator returns the boolean true or false. In Javascript, it returns the first or second operand, which is just as well since those values themselves are "truthy" or "falsey" already.
Hence 'Cat' && 'Dog' results in the value 'Dog', which is equal to 'Dog'.
Because you asked if true === (true && true). If you use a non Boolean in a Boolean operation, javascript will convert to Boolean. Non empty strings are "true" so it returns correct.
I'm guessing the language designers wanted to enable users to use the || operator as a "coalesce" operator, in the style of e.g. the "null coalesce" operator ?? in C#.
In other words, if you want a default value, you can use the following idiom:
var x = input || "default";
//x will be equal to input, unless input is falsey,
//then x will be equal to "default"

Categories