Why does it always return true? - javascript

Beginner question, sorry if it's not the right place to ask
Trying to learn how logic works in JS, can't figure this out
if (firstSymbol === "A" || "a" || "D" || "d") {
if (secondSymbol === "z") {
alert("It does!");
break;
}
}
I expect it to say "It does!" and break in case if the firstSymbol is A, a, D or d AND the secondSymbol is z , but for some reason it says "It does!" and breaks regardless of what the firstSymbol is and only checks if the secondSymbol is z.

Because you're checking whether "a" is true - it is always true:
console.log(!!"a");
You should be using includes and AND && in this case:
const firstSymbol = "D";
const secondSymbol = "z";
if (["A", "a", "D", "d"].includes(firstSymbol) && secondSymbol == "z") {
console.log("It does!");
}

function matchSecondSymbol(firstSymbol, secondSymbol) {
// By making FirstSymbol Uppercase, we can remove the other two conditions
firstSymbol = firstSymbol.toUpperCase();
if (['A', 'D'].includes(firstSymbol) && secondSymbol === "z") {
console.log('it Does');
}
else {
console.log('it does not');
}
}
matchSecondSymbol('a', 'z');
matchSecondSymbol('z', 'z');
matchSecondSymbol('a', 'y');

In Javascript there's something called truthy and falsy values. In summary, is how a value evaluates in a Boolean (true or false) context.
All values are truthy unless they are defined as falsy (i.e., except for false, 0, "", null, undefined, and NaN).
In your code, when you wrote:
if (firstSymbol === "A" || "a" || "D" || "d")
You are checking 4 boolean conditions:
firstSymbol === "A" - The result will depend on firstSymbol
"a" - Will always evaluate to true
"D" - Will always evaluate to true
"d" - Will always evaluate to true
So, since conditions 2, 3 and 4 will always be true, your code will always enter the if statement. If even a single one of these would be true the behaviour would be the same.
You can rewrite it in some ways:
if (firstSymbol === "A" || firstSymbol === "a" || firstSymbol === "D" || firstSymbol === "d")
or
if (["A", "a", "D", "d"].indexOf(firstSymbol) > -1)
or
if (["A", "D"].indexOf(firstSymbol.toUpperCase()) > -1)

Just to add something to the boilerplate, these are some examples to accomplish what you're trying to do, with tons of possibilities.
Tests covered:
using array.includes
using array.indexOf
using array.find
using array.some
WHY didn't your code work?
It didn't work because javascript evaluates the following expression: "A" || "a" || "D" || "d" to "A", because "A" is truthy. If you need to compare with multiple values, either use an array, either write the condition for each of them:
firstSymbol === "A" || firstSymbol === "D" ||...
Examples mentioned above:
/* Original code */
/*
if (firstSymbol === "A" || "a" || "D" || "d") {if (secondSymbol === "z") alert("It does!"); break;}
*/
let firstSymbol = "d", secondSymbol = "z";
// Using .includes
if (["A","a","D","d"].includes(firstSymbol) && secondSymbol === "z") console.log('it does, with .includes');
// Cleverer .includes due to the nature of the input.
if (["a","d"].includes(firstSymbol.toLowerCase()) && secondSymbol === "z") console.log('it does, with cleverer .includes');
// Using .indexOf
if (["A","a","D","d"].indexOf(firstSymbol) > -1 && secondSymbol === "z") console.log('it does, with .indexOf');
// Using .find
if (["A","a","D","d"].find(i => i === firstSymbol) && secondSymbol === "z") console.log('it does, with .find');
// Using. some
if (["A","a","D","d"].some(i => i === firstSymbol) && secondSymbol === "z") console.log('it does, with .some');

Order of Precedence decides
In each programming language, symbols are processed in order of their precedence order.
In Short:
AS the others already explained, your assignment
firstSymbol === "A" || "a" || "D" || "d"
would be processed as
(firstSymbol === "A") || ("a") || ("D") || ("d")
Link to how logical operators are processed: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

Related

Multiple Values after Comparison Operator [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;
}

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'));

Adding the OR operator to a quizz form makes it accept any answers

I'm having a weird problem when trying to create a question form that is validated with Javascript:
If I write my validation like this:
if (typedValue === "myAnswer" && clearedLevels === 1){doStuff}
Everything works. But I want to create several correct answers, so I write:
if (typedValue === "myAnswer"||"secondAnswer" && clearedLevels === 1){doStuff}
..and all of a sudden anything written to the input form is accepted as the answer.
A correct way of writing it is :
if ((typedValue === "myAnswer" || typedValue === "secondAnswer") && clearedLevels === 1) { doStuff() }
You cannot combine the condition (x === y || x === z) as x === y || z and expect the same results.
Any non-empty string in Javascript is true (yes, even the string "false"). Since "secondAnswer isn't empty, it's evaluated as true, and ORed with any other condition will result in true.
You are missing a comparison of typedValue to this literal, and presumably, brackets around the typedValue comparisons, since && has higher precedence than ||:
if ((typedValue === "myAnswer" || typedValue === "secondAnswer") &&
clearedLevels === 1) {
// doStuff
}
extending Akash Pradhan answer you could write
if (typedValue == "myAnswer" || typedValue == "secondAnswer" && clearedLevels == 1) { doStuff() }
but since the && has precedence over the || operator it would evaluate
if (typedValue == "myAnswer" || (typedValue == "secondAnswer" && clearedLevels == 1)) { doStuff() }

Why is this '=' syntax incorrect in this js snippet?

var hungry = true;
var foodHere = true;
var eat = function() {
if (hungry && foodHere === true) {
return(true);
} else {
return(false);
}`
};
The first line is the correct syntax. For a long time I was just saying hungry && foodHere = true... and I couldn't figure out (and still don't understand) why that is wrong. I understand the difference between = (assignment) and === (equal to). I assigned the variables to be true initially, so aren't I asking in the if statement if that's what they're set to? Why am I setting the variables = to in the var definition, but then when checking them I'm using the === value?
= is only used to assign variables. === or == are used to compare. For a good example, we must look into comparison operators.
Syntax
The syntax of comparison operators is fairly simple, use them to evaluate expressions. The comparasin operators are:
=== //strict equality
== //Parsed or partial equality
> //Greater Than
< //Less than
>= //Greater than or equal to
<= //Less than or equal to
To properly use these, you must know the proper syntax. For example, I can't do something like:
if(true == 1 === true) //do something
as that would invalidate the code, and slow it down by much using ==, which brings me to my next section.
Equality
The two equality operators in JavaScript are == and ===. They do two very different things.
===
The strict equality (===) tests whether two values are exactly equivalent, both in type and value.
==
The Parsed equality (==) tests whether two values are equalivent in value, but parses to try and connect different types.
Inequality
There are 2 main inequality value in JavaScript (!==) they are pretty self explainatory based on the equalities (===, and ==)
here's a chart explaining the three.
1 0 true false null undefined ""
1 === !== == !== !== !== !==
0 !== === !== == == == !==
true == !== === !== !== !== !==
false !== == !== === == == ==
null !== == !== == == == ==
undefined !== == !== == == === !==
"" !== == !== == == !== ===
Adding onto what #jcollum said, = defines a variable value, and if(something === true) simplifies into if(something). Similarly, if(something === false) simplifies into if(!something).
You also need to do comparisons separately. if(7 & 6 < 10) returns false because it is the simplified version of if(7 === true && 6 < 10).
It turns:
hungry && foodHere === true
into
hungry && true
or just
hungry
Using the assignment operator instead of the comparison operator is stopping your logic from working correctly.

How can I break the law of non-contradiction in Javascript?

The law of non-contradiction dictates that two contradictory statements cannot both be true at the same time. That means that the expressions
(a && !a)
(a == !a)
(a === !a)
should always evaluate to a falsy value, and
(a || !a)
should always evaluate to a truthy value.
Fortunately, though, Javascript is a fun language that allows you to do all sorts of sick things. I bet someone a small fortune that it's possible to convince Javascript to break the law of non-contradiction, or, at least, convincingly make it look like it's breaking the law of non-contradiction. Now I'm trying to make all four of the above code examples give the unexpected result.
What would be a good way to go about this?
The best I can do is:
[] == ![] // true
or
var a = [];
a == !a
Of course this is really doing [] == false // true and !![] == ![] // false. It's really just a technicality.
EDIT: This is really a joke, but does work:
var a = false; var b = function() { return a = !a };
console.log(!!(b() && !b())); // true
console.log(b() == !b()); // true
console.log(b() === !b()); // true
console.log(b() || !b()); // true
This one will do the trick:
var a = '0';
a == !a
(evaluates to true)
In this case, a == false and !a == false.
a=NaN;
var a=NaN,
A=[(a && !a), (a == !a),(a === !a),(a || !a)];
alert(A)
/* returned value: (Array)
NaN,false,false,true
*/
I still haven't found anything to break && and ===, but here's one for == and ||:
Object.prototype.toString = function() {
return false;
};
a = {};
b = (a || !a);
alert(a || !a); //alerts false
alert(b == !b); //alerts true

Categories

Resources