JavaScript logical operators questions? - javascript

I just don't understand how && and || work. I wrote up a small code to help myself out and it just doesn't make any sense to me. You would click a button and the startGame() would be called.
var startGame = function() {
var quizAnswers = {
name: prompt("What is your name?").toUpperCase(),
age: prompt("What is your age?"),
snack: prompt("What is your favorite type of snack out of the following: ice cream, apple, chips, cookies?").toUpperCase()
};
quizAnswers.confirmAge = function () {
while (isNaN(this.age) === true) {
this.age = prompt("The age that you entered- " + this.age + " -is not a number. Please enter a number.");
};
};
quizAnswers.confirmAge();
quizAnswers.confirmSnack = function () {
while ((this.snack !== "ICE CREAM") && (this.snack !== "APPLE") && (this.snack !== "CHIPS") && (this.snack !== "COOKIES")) {
this.snack = prompt("The snack you entered- " + this.snack + " -is unrecognized. Please enter: ice cream, apple, chips, or cookies.").toUpperCase();
};
};
quizAnswers.confirmSnack();
It would get name, age, and favorite snack and then check to see if the age is a number and the snack entered is one of the listed options. After messing with the while loop in the confirmSnack function, I figured out how to make it work, which is displayed above. But why is it && and not ||. And is there a way to shorten it like:
while (this.snack !== ("ICE CREAM" && "APPLE" && "CHIPS" && "COOKIES")) {
this.snack = prompt("The snack you entered- " + this.snack + " -is invalid. Please enter: ice cream, apple, chips, or cookies.").toUpperCase();
};
So the questions are to explain why &&(and) is used instead of ||(or) and if there is a way to shorten this code so i don't have to enter "this.snack !==" four times. I'm not an expert so please try to keep it simple.

The && operator is working just fine. This is actually a question of logic, not javascript.
You are asking the question while the answer is different from ALL of the possible answers.
It could be rewritten with || as the follwing:
while (!(this.snack == "ICE CREAM" || this.snack == "APPLE" || this.snack == "CHIPS" || this.snack == "COOKIES"))
Notice the ! operator in the beginning.
A shorter form to write it would be:
answers = ["ICE CREAM", "APPLE", "CHIPS", "COOKIES"];
while (answers.indexOf(this.snack) < 0) { ... }
Here you define a list of possible answers and you want to accept, and check if the answer is among them.

The && and || operators compare boolean values. (Boolean means true/false). That means if you execute 5 == 5 && 6 + 1 == 7 the interpreter does the following things:
Evaluate 5 == 5. The == operator returns true if both sides are equal (as you probably know). Since 5 == 5 is true, we look at the next value (if it were false, because of short circuit operators, it would return false immediately).
Evaluate 6 + 1 == 7. This is also true, so the returned value is true.
The && operator does not compare regular values such as "ICE CREAM" (well it does, but it converts it into a boolean value).
Now let's look at the code you provided:
this.snack !== ("ICE CREAM" && "APPLE" && "CHIPS" && "COOKIES")
First, the javascript interpreter executes ("ICE CREAM" && "APPLE" && "CHIPS" && "COOKIES"). Since all of those values are true, the value of that expression is true. So this comparison is essentially checking this.snack !== true, which is not what you want.
To solve your problem, I would suggest using indexOf. This checks if an element is in an array and returns -1 if there is no element. For example:
var validSnacks = ["ICE CREAM", "APPLE", "CHIPS", "COOKIES"];
while (validSnacks.indexOf(this.snack) === -1) {
// Do something
}

If you use or(||), if any of the sub-statements (e.g. this.snack !== "ICE CREAM") evaluate to true, the entire statement will be true, causing the prompt to be shown.
On the other hand, using and(&&), all of the sub-statements must be true for the entire statement to evaluate as true, which is the behaviour that you want - you only want the prompt to show if snack is not one of the 4 options.
There is no way to shorten the code in the way you suggest. One thing you could do would be to make an array with the 4 options in it and check if that array contains snack.

Related

Why does do-while not evaluate logical &&?

Here is a simple code snippet where I am ensuring the user input is a number and is between 1-3
do{
var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
}while(isNaN(choice) && (choice === 1 || choice === 2 || choice === 3));
While debugging I see the debugger does not even evaluate the part after && where I am keeping a check on the input to be among 1, 2 or 3
Weirdly enough, the do-while construct works fine if I just have :
do{
var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
}while(isNaN(choice));
Can someone tell me what am I missing here or doing wrong?
As your code looks now, you are looping as long as it's not a number and it's either 1, 2, or 3. Since those three are all valid numbers, the overall condition can never be true - if it's not a number then it won't be 1, 2 or 3, and if it's 1, 2 or 3 it won't be "not a number" (since it's a number).
From what you wrote, you want to keep looping if it's not a number or not one of those three:
do {
var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
} while (isNaN(choice) || !(choice === 1 || choice === 2 || choice === 3));
(I changed && to || and added a ! before the second part of the condition.)
However, since you are limiting it to three exact options anyway, you don't even need to check for NaN anymore, because as mentioned before, if it's 1, 2 or 3 it means it's not NaN anyway:
do {
var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
} while (!(choice === 1 || choice === 2 || choice === 3));
This becomes a bit easier to read by getting rid of the negation in the front, replacing === by !== and || by &&:
do {
var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
} while (choice !== 1 && choice !== 2 && choice !== 3);
An alternative way to simplify the previous code is to create an array with valid values and loop as long as this array doesn't include the actual input number:
do {
var choice = parseInt(prompt("Please select one of the following:\n1.ROCK\n2.PAPER\n3.SCISSORS\n[NOTE: Choose your selection by pressing a number between 1,2 or 3.]"));
} while (![1, 2, 3].includes(choice));
When the first statement of the while loop is false the compiler doesnt compile the other statements after && here in this example (choice === 1 || choice === 2 || choice === 3) because it doesn`t matter what the other statements result is. The while loop is not executed at all.
This is compiler optimation (Short-circuit evaluation) for more information look at this article: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND
Assume that when you prompt a non-nan value e.g. a number, isNaN evaluates false, thereby going into short-circuit evaluation. However, I think you want to accept one of 1,2, or 3 values. So shouldn't it be like !(choice === 1 || choice === 2 || choice === 3)? If one of them equals that value, no need to loop again.
A less complicated approach (avoiding parseInt, isNaN and multiple boolean checks) may be (snippet for the whole game ;):
Play it here
document.querySelector('button')
.addEventListener( 'click', () => location.reload() );
let choices = ['ROCK', 'PAPER', 'SCISSORS']
let choice = 0;
while ( !choices[+choice-1] ) {
choice = prompt(
`1. ROCK; 2. PAPER; 3. SCISSORS`, `Enter 1, 2 or 3`);
}
const values = {
yours: choices[choice-1],
mine: choices[Math.floor(Math.random() * 3 )]};
const tie = values.yours === values.mine;
const iWin = values.yours === 'SCISSORS' && values.mine === 'ROCK' ||
values.yours === 'ROCK' && values.mine === 'PAPER' ||
values.yours === 'PAPER' && values.mine === 'SCISSORS';
console.log(`your choice: ${values.yours}, against: ${values.mine}. ${
tie ? 'Tied...' : iWin ? 'You lost' : 'You win!'}` );
<button>Again...</button>

What can I do to make code be executed while the answer is one of a multiple conditions?

I tried to make that a code runs when x, determinated by a prompt is one of the four answers. With only one possibility it works well, but when I add more using && the program do nothing. (At the end of the program i put a break to execute the code only one time)
That's a short version of how the programm works...
var x = prompt("Ready?");
while(x == "yes"){
window.alert("...Example...");
break;
}
And how I want to make it but doesn't works...
var x = prompt("Ready?")
while(x == "Yes" && x == "yes" && x == "yeS" && x == "YES")
window.alert("...Example...");
break;
}
How can I do to make it works?
I would just use .toLowerCase() before the comparison so you don't have to deal with all different ways to capitalize a word.
var input = prompt("Ready?");
var x = input.toLowerCase();
while( x == "yes" )
window.alert("...Example...");
break;
}
Then again, if you only need yes or no as options, I'd use a window.confirm instead of a window.prompt.
Edit: Hmm, if the question is that the answer HAS to be yes written in one of those 4 ways, I'd go for the array approach so you can add other options later on:
var allowed_answers = [ 'yes', 'Yes', 'yeS', 'YES' ];
if ( allowed_answers.includes( x ) ) {
}
Use || instead of &&, and there's no need for a while statement, use if instead:
var x = prompt("Ready?")
if (x === "Yes" || x === "yes" || x == "yeS" || x == "YES") {
window.alert("...Example...");
}
|| means “or”, i.e. at least one of the conditions has to be true. If you use “and”, it means all of the conditions need to be true, which cannot possibly work.
Maybe you're trying to do this
do{
var x = prompt("Ready?").toLowerCase();
//toLowerCase() method convert (YES, Yes, yeS, etc) to (yes)
if(x === "yes"){
//If the condition is true, the loop breaks
window.alert("...Example...");
break;
}
}while(true)

If/Else Statement Returning false positives

In my code, I have this if/else statement to deal with a situation in which the numbers and letters both return cont = false. I have tried running just this code, with the same result. Obviously, it should execute the code in the else statement. Does anyone have any ideas?
var input = prompt()
if (input == null || " ") {
//Cont determines whether or not to continue
console.log("cont = false");
var cont = false;
}else{
console.log("cont = true");
var cont = true;
}
Because that code is not how you check one input against two values.
if ( input == null || " " )
should be
if (input==null || input == " ")
input == null || " "
evaluates to (result of your comparison) || " ". Now since " " (a non-empty string) is a truthy value this always evaluates to true.
For order of evaluation -
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
Adding to the other replies which are all correct about the || operator and precedence.
Using == is not a good thing to do in most cases, not least because 0 == null etc - if you're checking if it's actually null or an empty string then something like this is safer:
if (input === null || input.trim() === "") {
...
This checks type as well as content, so won't be able to give false positives. though if input isn't a string it will complain.
Thank's so much! As a summary of all of the answers recieved so far:
The OR operator (||) is comparing input == null to " ", the latter of which always evaluates to true
=== is better than ==
Thanks again for all the help and support!

Javascript skips function

I an working on a project for an Introductory Programming class so I'm using basic javascript. This is our first project with functions and for some reason I can't seem to make it work. I called all my variables and created the function before the program starts but for some reason it skips over running the function in my program. Any help would be appreciated.
This is just the beginning of my program, I don't wanna write the rest of the code until I figure out why this part is broken, thats why the program doesn't do anything but close the window if it doesnt pass the tests.
// 1 Declare Variables
var numTrees;
var counter = 0;
var answer = "no";
function treeFunction(answer, counter, numTrees) {
while (answer == "no" && counter < 3) {
if (numTrees == 5, 10) {
answer = "yes";
} else if (numTrees < 5 || numTrees > 10) {
alert("That is an incorrect value.\nThe sample size should be less than 5 or greater than 10.\nPlease try again.");
answer = "no";
numTrees = prompt("Please reenter the amount of trees in your sample.");
counter + 1;
}
}
if (answer == "no") {
alert("You have entered an incorrect number too many times.\nThe Program will now end.");
window.open('', '_self', '');
window.close();
} else if (answer == "yes") {
return;
}
}
// 2 Prompt the Instructor for the number of Trees
numTrees = prompt("How many trees are in your sample?");
alert("You have entered: " + numTrees);
treeFunction(answer, counter, numTrees)
document.write(numTrees); {
document.write("<br/> <br/>" + "End of Program.");
}
You have;
if(numTrees == 5, 10)​
The erroneous comma is causing the if to evaluate the truthy expression 10 so its always passing the test, to test for 5, 6, 7, 8, 9 or 10;
if(numTrees >= 5 && numTrees <= 10)
The way you are using the comma in this line has a special meaning:
if(numTrees == 5, 10)​
Essentially what this does is returns the value of 10 (the second operand) when cast to a boolean, which is not 0, so it is true.
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Comma_Operator
You probably meant to use OR (||):
if(numTrees == 5 || numTrees == 10)​
Or check numTrees against a range:
if(numTrees >= 5 || numTrees <= 10)​
On a side note, in javascript it is recommended that you always use identity comparison (===) instead of regular comparison (==):
if(numTrees === 5 || numTrees === 10)​
if(numTrees == 5, 10)​ doesn not mean If numtrees is equal to 5,6,7,8,9, or 10
change it to
if(numTrees >= 5 || numTrees <=10)​
if (numTrees == 5, 10) {
answer = "yes";
}
This is an odd-looking construct that I've never seen before. I'm assuming you believe it means "is numTrees within the range 5 to 10?", but that's not the case. Without checking, I think it essentially means you're checking two things at once:
is numTrees equal to 5?
is 10? (this essentially means "is 10 not 0", which of course is always true).
Since the 2nd condition you're checking is always true, you're always setting answer to "yes". As a result, your loop always runs exactly once - it starts up, checks answer is "no", sets answer to "yes", and that immediately stops the loop.
You need to change your condition to if(numTrees >= 5 && numTrees <= 10)
What you want is something more like this:
if (numTrees < 5 || numTrees > 10) {
alert("That is an incorrect value.\nThe sample size should be less than 5 or greater than 10.\nPlease try again.");
answer = "no";
numTrees = prompt("Please reenter the amount of trees in your sample.");
counter + 1;
} else {
answer = "yes";
}

Is there a way to create a loop which while only stop if specific strings are entered?

What I'm trying to do is make a loop which prompts the user for information and will only stop if certain strings are entered. Specifically, I want it only to accept certain letters, both upper and lowercase. Here's what I have so far:
do
{
salesP = prompt("Enter the initial of the first name of the salesperson: ", "");
}while (salesP != "C" || salesP != "c")
Basically the while part is completely wrong and I know it. I've tried everything I can think of, and the best I can do is get it to accept a single variable. I also need it to accept d, x, and m, both cases.
Option 1
Permanent loop with an if statement, can use multiple if statements or other control structures to check for when to break.
while 1:
if(raw_input('Enter some data please:') == specialString):
break
Option 2
Part of loop
tempstring = ""
while (tempstring != specialString):
tempstring = raw_input('Enter some data please:')
Option 3:
Recursion
def dataEntry(a,b,c):
#data validation statements that fail on first iteration
#statements to prompt user about data
dataentry(a,b,c)
As far as how to check for the right string, I would recommend regular expressions. Googling for "regex" examples is much better than me trying to explain it.
Something else to play with that if you are new you should become REALLY familiar with when doing string comparison is to eliminate case from the equation completely:
do
{
salesP = prompt("Enter the initial of the first name of the salesperson: ", "");
}while (salesP.toLowerCase() != 'c')
That code is almost correct. You simply use the incorrect boolean operator in your while statement. You're using OR (||) where you should use AND (&&).
So:
do
{
salesP = prompt("Enter the initial of the first name of the salesperson: ", "");
}while (salesP != "C" && salesP != "c")
just another approach
function promptSalesP(){
var _salesP = prompt("Enter the initial of the first name of the salesperson: ", "");
if(_salesP.toLowerCase() == "c")
return _salesP;
else
return promptSalesP();
}
var salesP = promptSalesP();

Categories

Resources