Javascript printing all if conditions in textbot [duplicate] - javascript

This question already has answers here:
What's the prettiest way to compare one value against multiple values? [duplicate]
(8 answers)
Closed 4 years ago.
This is literally the first thing I have ever coded and I am self-taught, so I'm sure it's a mess and I've made a dumb error, but after an hour of looking up the issue and trying things I cannot solve this.
To try and teach myself very basic javascript concepts I've written a textbot that has existential conversations with you. The problem is that regardless of user input, all the if statements for the condition of whatDream are printing in a row. Can anyone tell me what I've screwed up here? Apologies if my methods are wack - 100% of what I'm doing is from self teaching and letting myself flail to learn, and I'll appreciate any advice.
function yesHappy (){
alert ("Good for you. To be happy as a human is a great gift.");
alert ("The content human starts over again everyday, in spite of all they know, against all they know.");
alert ("If one advances each day confidently in the direction of their dreams, and endeavors to live the life which they have imagined, they will meet with a success unexpected in common hours.");
var g = 0
while (g < 2) {
g = 0
var whatDream = prompt ("What is your dream?");
if (whatDream === "success" || "Success" || "power" || "Power" || "wealth" || "Wealth"){
alert ("That is a goal that takes much will in the earthly domain, and is not one I can readily reccomend.");
alert ("But, read your fate, see what is before you, and walk into futurity.");
g = 3
}
if (whatDream === "friends" || "Friends" || "family" || "Family" || "love" || "Love"){
alert ("To surround oneself with others fulfills a basic human goal to be social, thus your dream is only natural.");
alert ("Properly speaking, a human has as many social selves as there are individuals who recognize them.");
alert ("To all of these you surround yourself with, see in your goals only to show your true social self.");
g = 3
}
if (whatDream === "fun" || "Fun" || "charity" || "Charity" || "faith" || "Faith" || "travel" || "Travel"){
alert ("These are honorable dreams, chosen to bring joy to yourself and others.");
alert ("Above all however, avoid falsehood, especially falseness to yourself.");
alert ("Be true to your purpose.");
g = 3
}
if (g === 0){
alert ("Though knowledge is the plague of life, and consciousness an open wound in its heart, I am still sad to say I don't know what you mean.");
alert ("Let's try that again.");
}
}
}

You need to refactor all your conditional statements. For example: This one
if (whatDream === "success" || "Success" || "power" || "Power" || "wealth" || "Wealth")
Would have to be translated to:
if (whatDream === "success" || whatDream === "Success" || whatDream === "power" || whatDream === "Power" || whatDream === "wealth" || whatDream === "Wealth")
Which does what you want: Checks to see if whatDream equals any of those. Or alternatively you can use a data structure and use a method to check if the string exists in that data structure- but above is the simplest refactoring you'd have to do.
Javascript has "truthy" and "Falsey" values. Strings like "Success" map to true whereas "" map to false. So your conditionals were always evaluating to true because strings with length > 0 are "truthy". This is probably more explanation that you need- but its important to know that in the future of javascript development.
In essence- your issue is that you weren't checking the values of whatDream in your boolean logic. The above simple refactoring I did fixes it.
If you're curious: You can read up on truthy and falsey values here:
https://j11y.io/javascript/truthy-falsey/

Related

I've made an infinite loop and can't seem to figure out what I did wrong

I'm writing a program for a simple game of Odds and Evens, but I can't seem to figure out what's wrong with my while loop.
Game rules: https://en.wikipedia.org/wiki/Odds_and_evens_(hand_game)
It's meant to make it so that while the user doesn't enter either odds, Odds, evens, or Evens an alert comes up saying 'Please enter either odds or evens'.
But, whenever I run the code, it just turns into an infinite loop, repeating the alert, no matter what I put in. Even if it is the correct response I want.
var oddEven = prompt('Would you like to be odds or evens?', 'Odds')
while (oddEven != 'odds' || oddEven != 'Odds' || oddEven != 'evens' || oddEven != 'Evens') {
oddEven = prompt('Please enter either odds or evens');
}
I am very new to programming and just started learning a couple months ago so any advice would be appreciated.
Thanks for the help :)
Imagine a user gives the input "Odds", what happens in your if statement?
oddEven != 'odds' is false, but we still need to check the others! We need to check the others because you have written || which means "or" - javascript will keep going through each statement until one of them is true.
oddEven != 'Odds' is true. Because it is true, your while-loop immediately continues, again because you have used || - if ANY of the statements is true the code will stop checking statements and continue the loop.
There are lots of ways to fix this but I think the following is best for comparing to how you got stuck:
var oddEven = prompt('Would you like to be odds or evens?', 'Odds')
while (
!(oddEven == 'odds' || oddEven == 'Odds' || oddEven == 'evens' || oddEven == 'Evens')
) {
oddEven = prompt('Please enter either odds or evens');
}
Now in our example, oddEven == 'Odds' is true, but because the whole section is negated by the bang ! at the start, we're taking the opposite of that, so false.
A tidier way of doing this could be as follows:
var oddEven = prompt('Would you like to be odds or evens?', 'Odds')
while (!['odds', 'Odds', 'evens', 'Evens'].includes(oddEven)) {
oddEven = prompt('Please enter either odds or evens');
}
This says "while this list of inputs does not include oddEven".
So it's an Or, any condition that satisfies even one, will evaluate to true. So if I enter 'boo', oddEven != 'boo', and therefore the rest evaluates as true. A better way would be
while (oddEven in ['odds', 'Odds' ...]):
oddEven = prompt('Please enter either odds or evens')

Codecademy - Looking for clarification on syntax ( === "number" )

I'm working my way through the Codecademy 'Intro to JavaScript' course. I've just came across an example section of code that has confused me a little and doesn't seem to be explained. I've looked at the Mozilla documentation and think I understand but I'm really just looking for clarification on the subject.
let restaurant = {
_name: 'Italian Bistro',
_seatingCapacity: 120,
_hasDineInSpecial: true,
_entrees: ['Penne alla Bolognese', 'Chicken Cacciatore', 'Linguine
pesto'],
set seatingCapacity(newCapacity) {
if (typeof newCapacity === 'number') { // THIS LINE
this._seatingCapacity = newCapacity;
console.log(`${newCapacity} is valid input.`);
} else {
console.log(`Change ${newCapacity} to a number.`)
}
}
My question - Does 'number' here mean a number (12, 343 etc.) rather than the string 'number' in all cases? Or is it only within the typeof operator?
I'm assuming it's a silly question but it's one that threw me off. Thanks.
=== is used to check for strict equality. Consider the following example
0 == false //<== returns true
0 === false //<== returns false
In your example is not necessary, as typeof will never return any value that could be equal to number without being the number string itself. But it's considered good practice to use === (although I personally think it depends on what you are comparing)
(list of possible returned values for typeof here)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof

Best way to refactor complex if expression [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have just come on board to a big e-commerce project that has an angularJS front-end. I have been tasked with adding a lot of complex features to the checkout pages... which already have a lot of complex logic.
To make things harder I keep coming across lots of if statement expressions like the one below which are making it hard to understand and it is a slow process going through this code with many of these type of if expressions.
Some of these expressions are pretty critical and are sometimes even longer... There are no unit tests and when I ask other devs what this is checking for and why (just to be sure I understand) I usually get pointed to someone else rather than an explanation.
if ((!previousBillingAddress) || (previousBillingAddress && previousBillingAddress.id !== bag.paymentAddress.id)){
console.log('all of the above was true'); // just a dummy log
} else {
console.log('all of the above was false'); // just a dummy log
}
Does anyone have a good tip for refactoring these types of expressions?
I thought of breaking them down into functions that have descriptive names and the functions could return true or false but Im not sure if there is a better way.
Let there be
A = previousBillingAddress
B = previousBillingAddress.id !== bag.paymentAddress.id
then your expression is:
if (!A || (A && B)) {
log1
} else {
log2
}
What we can do we with !A || (A && B)? It's equal to !A || B:
A | B | !A | A && B | !A || (A && B) | !A || B
==========================================================
1 | 1 | 0 | 1 | 1 | 1
1 | 0 | 0 | 0 | 0 | 0
0 | 1 | 1 | 0 | 1 | 1
0 | 0 | 1 | 0 | 1 | 1
That's why your expression is equal to:
if (!previousBillingAddress || previousBillingAddress.id !== bag.paymentAddress.id) {
console.log('all of the above was true'); // just a dummy log
} else {
console.log('all of the above was false'); // just a dummy log
}
TL;DR
Above table is only check if !A || (A && B) is equal to !A || B. How to guess !A || B? In case of such expressions it's good to play with following rules:
A == !(!(A)) (rule 1)
!(A && B) == !A || !B (rule 2)
!(A || B) == !A && !B (rule 3)
A && (B || C) == A && B || A && C (rule 4)
So we have !A || (A && B), let's play. Due to rule 1 it's equal to
!(!(!A || (A && B)))
Now we use rule 3:
!(!(!A || (A && B))) == !(A && !( A && B))
Rule 2:
!(A && !( A && B)) == !(A && (!A || !B)) (*)
Due to rule 4:
A && (!A || !B) == (A && !A) || (A && !B)
We have (A && !A) || (A && !B) and it can be reduce to (A && !B). Now we can back to (*) and we have:
!(A && (!A || !B)) == !((A && !A) || (A && !B)) == !(A && !B)
With rule 2 we got:
!(A && !B) == !A || B
You can drop the previousBillingAddress && part - in the second operand of the || you already have estblished that previousBillingAddress is not falsy. That would make the overall condition
if (!previousBillingAddress || previousBillingAddress.id !== bag.paymentAddress.id) {
console.log('all of the above was true'); // just a dummy log
} else {
console.log('all of the above was false'); // just a dummy log
}
which seems short enough for me. If not, make an appropriately named helper function to which you pass the previousBillingAddress and the bag.
In my personal opinion, i think you can refactor and encapsulate the validation/check inside of a function, then if the same validation applies to other part of your code (file/module/etc..), you can reuse it. In this case you are using angular, so might be good to use an angular custom service for this type of business validations, since they also can manipulate the scope
Comments are our best friend. You want to make sure that the next person to take a look at your code knows exactly what it is supposed to do and from that, it will be quicker and easier to see exactly what it is doing.
In this case the expression in the if statement can be shortened. This is how I would comment it with almost a pseudocode approach:
// we need to check if the user has, and is using, a previous billing address
if (previousBillingAddress && previousBillingAddress.id === bag.paymentAddress.id)){
// the user is using a previous billing address
// do some work with the previous billing address
} else {
// the user is using a new address
// do some work with the new address
// save the new billing address
}
Note that previousBillingAddress is the main subject of this if statement. If we are checking for previousBillingAddress then in our first block we want to make sure we deal with what happens if we have a previous billing address. It's more logical that way.
It makes a lot less sense to check if we don't have a previous billing address and then what do we do if we have one.
Look how clean and logical it is! <3
I recommend hoisting the complex conditionals into Boolean variables (or constants, if your supported level of JS allows you to use const). For example:
var weakPrevBillingAddress =
!previousBillingAddress ||
(previousBillingAddress &&
(previousBillingAddress.id !== bag.paymentAddress.id));
if (weakPrevBillingAddress) {
console.log('judged weak previousBillingAddress');
// other processing expected here
} else {
console.log('judged strong previousBillingAddress');
// other processing expected here
}
As you and philip yoo suggest, you could hoist the conditional into a Boolean helper function. But most of the ways of defining such functions will put the logic farther away from the point of use, making comprehension harder. Boolean variables (a.k.a. "predicates") can be easily defined close to their use (e.g. right before your if statement). So there isn't much additional distance, but they still separate the computation of the Boolean value from its use. Your ability to focus on the computation separately can make things simpler and more comprehensible. As shown above, it also allows you to split long
lines and use indentation for better clarity.
I don't know if you have the flexibility to rename existing variable names. If you do, the ones you're using are exceedingly long. Long names can help increase understanding, but a 22-character name repeated several times per line is distracting, not clarifying. Shorter names, either for the source values, or just for the predicates you compute, can help. E.g.:
var weakPrevBA = !prevBA ||
(prevBA.id !== bag.paymentAddress.id);
Choosing good variable names is an art, and developer tastes about "how much description is enough" vary. But in an app that deals with billing addresses all the time, line after line after line, spelling out billingAddress every time doesn't necessarily help. If you're reading the code and comments, you probably are highly aware you're dealing with billing addresses. If not, add a quick comment, rather than spell out the full concept multiple times per line.
Note that I've also simplified the Boolean expression in this shorter example. (This was also suggested by Bergi) That can be a good idea--as long you're sure it can be simplified correctly. However, do this only with great caution. You don't have unit tests, so you have no easy way to test if simplifications are truly identical. And you're dealing with complex code. I recommend keeping the original Boolean expressions, at least to start (possibly with shortened names). That reduces one place bugs can creep in, at least until you understand the code more fully. The better you understand the code, and the simpler you have made it (e.g. by adding computed predicates, rather than long, complex expressions inside conditionals), the more freedom and safety you have in rewriting expressions.
Something like this
var billingId = previousBillingAddress && previousBillingAddress.id;
if (billingId || billingId === bag.paymentAddress.id){
console.log('all of the above was false'); // just a dummy log
} else {
console.log('all of the above was true'); // just a dummy log
}
what i did
since you are using if and else its not a good practice to use negation in the if statement. so i removed that
if you only want the negated part (without an else)
if (!(billingId || billingId === bag.paymentAddress.id)){
console.log('all of the above was true'); // just a dummy log
}
the && will return the first false, or the last true value. so billingId will equal false or the id. building upon that, your first if is checking if its "falsey" continue, so you can use the same variable as well.

How do I write a script for a IF/OR statement for multiple instances?

I'm trying to write a script rule that's like the following:
if (Field(A) == "Yes" || Field(B) == "Yes" || Field(C) == "Yes")
return "TITLE"
else
return ""
I have it functioning if I'm only doing "if A OR B", but does not work if I add another field into the mix.
What I'm trying to accomplish is offering a list of items that a user has to choose "yes" or "no" for. If ANY of the three is a "yes", I need the title to show up. So if NONE of them is a "yes", then the title will not show up.
Any suggestions? I've searched around multiple sites and cannot find anything that works.
That code should work, so if a given field is not working, then the value for that field is probably not what you're expecting it to be. I suggest using console.log(myFirstVar, mySecondVar, myThirdVar) immediately before the if statement to see what your values are before they hit the if.
Also, it's good practice to use === instead of ==. They usually resolve in the same way but == will return a match in many cases that === does not. Specifically == treats all truthy and falsey values as equal, such that if you're doing an if (myVar == false) check, you'll get true if myVar is 0, false, undefined, etc.
Your code just work fine you can Play with the following Fiddle to see that what are you doing is right.
Using span for displaying the change on test.
HTML :
<span id="title"></span>
JS :
var fieldA = 'Yes';
var fieldB = 'No';
var fieldC = 'No';
if (fieldA == "Yes" || fieldB == "Yes" || fieldC == "Yes")
document.getElementById('title').innerHTML ="TITLE";
else
document.getElementById('title').innerHTML = "";

Fastest way to perform this? Ternary Operator? Switch? Array?

What is the fastest way to perform this? The vars in the parens on the left return boolean and they represent window size ranges. (e.g. o1281 returns true for screens 1281 and up, o1025 returns true for 1025 and up, etc.)
markup = // ternary triangle (the rows set the markup priority at each band)
( o1281 ) ? r1281 || r1025 || r961 || r641 || r481 || r320 || r0 || omarkup:
( o1025 ) ? r1025 || r961 || r641 || r481 || r320 || r0 || omarkup:
( o961 ) ? r961 || r641 || r481 || r320 || r0 || omarkup:
( o641 ) ? r641 || r481 || r320 || r0 || omarkup:
( o481 ) ? r481 || r320 || r0 || omarkup:
( o320 ) ? r320 || r0 || omarkup:
( o0 ) ? r0 || omarkup:
omarkup;
I was thinking maybe break it into 2 ranges based on the middle (o641) condition.
Is it worth it?
Okay so what you are doing is looking for the first truthy o-value going in descending order, and once you find one you are looking for the first truthy r-value whose name is <= this o-value. Finding none, you wish to return the value omarkup.
Because you only have a few o-values and r-values, your code, as "interesting" as it may be, appears to make the least number of tests possible.
I can't see how switches or hashes would help, since you do appear to be searching in descending order for the first truthy value.... Because of this, I don't see why splitting would help performance either. Leave it as is, or, if you prefer readability (as many programmers do), make objects for which 1281, 1025, etc. are fields.
Also, worrying about performance is usually something one does when faced with an operation that will executed many, many times. Is this the case here? This looks like something you would only execute once, assuming the o and r values don't change. (Just an FYI.)
ADDENDUM
Based on the comment added to the question above, it looks like an operation you would like to execute multiple times. In this case it probably okay to self-optimize at the JavaScript level, although modern compilers are pretty good. The biggest concern from a code-review perspective would be that the values 1281, 1025, 961, 941, and so on are laid out manually and are part of the source code, so maintenance, such as adding new size-values here is, well, tricky and error-prone. That said, based on what you have shown, I think it is safe to say your JavaScript as written is the best obtainable given a naive compiler. You can always shoot for an implementation that defines these values exactly once and then profile it to see if it is "fast enough". For example you can define an array such as
var sizes = [1281,1025,961,641,481,320,0]
and loop through, but yes, there is overhead in such implementations.
One issue that might help you here is to consider carefully what can and cannot be cached. This could help speed up future executions of this code.

Categories

Resources