I am trying to create a loop to include an else statement. It works perfectly with the if statement as below but when trying to put in the else statment it either shows nothing or creates 6 loops. Im assuming I am putting the else statement in the wrong place. Can someone please explain to me a) where to put the else statement and b) the nesting criteria of the ending curly braces inside a function
Heres what ive got and it works perfectly until i place the else statement in. thanks
var sports = ["golf", "cricket", "tennis", "badminton", "squash"];
function checkSport(sportToCheck) {
for (var i = 0; i <= sports.length; i++) {
if (sportToCheck == sports[i]) {
alert("yes we offer that sport");
}
}
}
checkSport("tennis")
Based on your variable names, I guess you don't have to use else in this context but you would like to end the loop/function as soon as the sport is found:
function checkSport(sportToCheck) {
for (var i = 0; i <= sports.length; i++) {
if (sportToCheck == sports[i]) {
alert("yes we offer that sport");
return; // stop the execution of the function
} else {
console.log("Do nothing so you don't need this else statement.");
}
}
alert("No we don't offer that sport"); // If the loop ends and cannot find any match
}
Because your function is check() and to respect Do One Thing rule, it's better to return true or false.
There are many ways to solve your issue but I prefer find().
var sports = ["golf", "cricket", "tennis", "badminton", "squash"];
function checkSport(sportToCheck) {
return sportToCheck === sports.find((sport) => sport === sportToCheck);
}
console.log(checkSport("football")); // Expect : false
console.log(checkSport("tennis")); // Expect : true
If you want to improve #Hangindev answer you can do this:
for (sport of sports) {
true === (sportToCheck === sport) && alert("yes we offer that sport");
}
No need for else statements. Simply run through each possible value in the sports array, and use the return statement to pause further script execution within that function.
The function returns either true or false depending on whether the string is inside the sports array.
var sports = ["golf", "cricket", "tennis", "badminton", "squash"];
function checkSport(sportToCheck) {
for (var i = 0; i <= sports.length; i++) {
if (sportToCheck == sports[i]) {
alert("yes we offer that sport");
return true;
}
if (i == sports.length) {
alert("sorry we do not offer this sport");
return false;
}
}
}
checkSport("tennis")
You could use this for something like:
if (checkSport("tennis")) {
// sport exists
} else {
// sport does not exist
}
Related
I am trying to load interactivly some questins from questions' array (q) into my page and after student clicks at one of the 2 questions register the answer and change the question using js while loop. What is my mistake that it doesn't work?
var q = [
['NFR', 'Reusability'],
['NFR', 'Robustness'],
['FR', 'Reporting Requirements'],
['FR', 'Historical Data']
];
var correct = 0;
var incorrect = 0;
var total = q.length;
var i = 0;
document.getElementById('nick').innerText = name;
document.getElementById('question').innerText = q[0][1];
var nfr = document.getElementById('non-functional');
var fr = document.getElementById('functional');
function callback(ans) {
if (q[i][0] === ans) {
correct++;
} else {
incorrect++;
};
if (i < q.length - 1) {
i++;
document.getElementById('question').innerText = q[i][1];
} else {
location.href = "answer.html";
}
}
nfr.addEventListener('click', callback('NFR'));
fr.addEventListener('click', callback('FR'));
Your while loop is looping endlessly, because the only thing it does logically is set toNext to False, set some event listener callbacks and then evaluate toNext again, which will always be False. So i++ will never be called and i < q.length will always be True.
Get rid of the while loop. Write a separate function that evaluates the answer and updates your window with the next question. Use that function as callback for the click events.
In a callback function this will be set to the object calling the function, so you could write a function like this:
function callback() {
if (this.id == q[i][0]) {
window.correct++;
} else {
window.incorrect++;
}
i++;
set_question(i); // Logic to set the i-th question.
}
Edit
function callback(ans) {
// This function will return
// another function with the ans
// variable set, which in turn
// will be called as a callback
// when needed by the 'click' event.
return function () {
if (q[i][0] === ans) {
correct++;
} else {
incorrect++;
};
if (i < q.length - 1) {
i++;
document.getElementById('question').innerText = q[i][1];
} else {
location.href = "answer.html";
}
}
}
Event listeners are executed asynchronously and the code you write might assumes that the listeners can block loop execution.
To fix this, try removing the loop and move the logic of switching to the next question into the listener callback.
I am fairly new to JavaScript and I have a question regarding how to optimise if statements.
I will show you two scenarios.
//first
var number = 10;
var calculationOneResult = functionOne(number);
var calculationTwoResult = functionTwo(number);
if (calculationOneResult === true) {
//stuff
} else if (calculationTwoResult === true) {
//more stuffs
}
//second
var number = 10;
if (functionOne(number) === true) {
//stuff
} else if (functionTwo(number) === true) {
//more stuffs
}
Here is my question:
In the first scenario, I am calculating two times.
In the second one, if the first function returns true, will it calculate the second elseif statement or will it skip it after doing the stuff ?
The following code:
if(statement1) {
// stuff
} else if(statement2) {
// other stuff
}
is equivalent to
if(statement1) {
// stuff
} else {
if(statement2) {
// other stuff
}
}
as there is no elseif in JavaScript - see documentation.
So the answer is any function in statement2 will be simply skipped.
Nothing in an else clause executes if the if expression tests as true, so the second version of your code will definitely save a function call in such cases.
I need to pass certain parameters into a function and have that function pull from an array based on the arguments passed to it. It's hard to explain, so I'll show you what I'm trying to do.
function SearchDeck(deck,...){
var tryagain = true;
do{
if(deck[0].property == value){
//do something;
tryagain = false;
}
else{
deck.splice(0,1);
}
}
while(tryagain);
}
There are multiple decks to look in, the proper deck will be passed in. I want to always be drawing off the top of the deck (index 0 of the array). I need to draw continuously until I find a card that matches what I'm after. I splice out the 0 index if it doesn't match. What I'm after is dynamic, varying across the properties or even the operators I would use.
Some examples of if statements I would have are...
deck[0].color == "orange"
deck[0].value >= 5
deck[0].value < -4
I could make multiple functions or have the function fork based on an argument, but that doesn't seem like the best way to go about this.
If I'm understanding this correctly, you want the behavior of the if(deck[0].property == value) to be different for each invocation of the SearchDeck(...) function?
My recommendation would be to pass in a function:
function SearchDeck(deck, validationFunction, ...){
var tryagain = true;
do{
if(validationFunction(deck[0])){
//do something;
tryagain = false;
}
else{
deck.splice(0,1);
}
}
while(tryagain);
}
Then when you call the code, you can do:
SearchDeck(deck, function(firstCard) { return firstCard.color == "orange" }, ...);
SearchDeck(deck, function(firstCard) { return firstCard.value >= 5 }, ...);
SearchDeck(deck, function(firstCard) { return firstCard.value < -4 }, ...);
Or, if the cases you're looking for might be reused, it might also be cleaner to make those named functions:
function validateColor(firstCard) {
return firstCard.color == "orange";
}
function validateHighValue(firstCard) {
return firstCard.value >= 5;
}
function validateLowValue(firstCard) {
return firstCard.value < -4;
}
SearchDeck(deck, validateColor, ...);
SearchDeck(deck, validateHighValue, ...);
SearchDeck(deck, validateLowValue, ...);
It sounds like you may be interested in the typeof operator:
if (typeof deck == 'object') { ... }
if (typeof deck[0].color == 'string') { ... }
if (typeof deck[0].value == 'number') { ... }
Alternatively:
if (deck[0].hasOwnProperty('color')) { ... }
This is what I came up with. You need to push the way of check (either "== 'oragne'" or "<3") as string.
function searchDeck() {
var deck = Array.prototype.slice.call(arguments, 1),
tryagain = true,
string = deck[deck.length - 1];
deck.pop();
while (tryagain) {
if (eval('deck[0].property' + string)) {
//do something;
alert('card found');
tryagain = false;
} else {
deck.splice(0, 1);
}
}
}
Hope this is what you wanted ;)
Here is a working jsfiddle example, of course there might be a more elegant way, this is just what I came up with. Note that eval can be dangerous, so you should be carefull if user picks what the test will be (the string pushed into the array).
I'm trying to find a good way to take a string as input for a conditional statement so that I can check against a list of conditions by iterating through an array of them. Basically, I'm wondering if I could do something like this:
// Would check if foo is equal to one, bar is true, and et is a string containing 'cetera'
var conditions = ["foo==1","bar==true","bar","et=='cetera'"];
for (var i=0;i<conditions.length;i++) {
if (conditions[i]) { console.log("Do stuff..."); }
}
I've thought of eval, but I wonder if it'd be a security risk. The files this code is in don't use PHP or any server software, but the host it runs on does have server software, and I don't know if it should be avoided.
Just drop the strings.
var conditions = [foo == 1, bar == true, bar, et == 'cetera'];
for (var i=0;i<conditions.length;i++) {
if (conditions[i]) {
console.log("Do stuff...");
}
}
This will populate conditions with a bunch of boolean values. You can then loop over it to see if any of them are true.
Edit: This will print "Do stuff..." every time a condition is true. So if foo == 1 is true and et == "cetera", then "Do stuff" will be printed twice. If that isn't what you want, then define an any function like this:
function any(arr) {
for (var i = 0; i < arr.length; ++i) if (arr[i]) return true;
return false;
}
You can then use if (any(conditions)) console.log("Do something...");
Edit 2: If you initialize conditions way before you are checking, (and values might change) wrap each one in a function (although it is a lot more typing). So for example:
var conditions = [
function() { return foo == 1; },
function() { return bar == true; }
// and so on...
];
Similarly, you would have to change if (conditions[i]) { console.log("Do stuff..."); } to if (conditions[i]()) { console.log("Do stuff..."); }
What command I must use, to get out of the for loop, also from //code inside jump direct to //code after
//code before
for(var a in b)
{
switch(something)
{
case something:
{
//code inside
break;
}
}
}
//code after
You can use label. Have a labeled statement and break to that label. outerLoop is the label I have used here.
//code before
outerLoop:
for (var a in b) {
switch (something) {
case 'case1':
//code inside
break outerLoop;
}
}
//code after
use another variable to flag when you need to exit:
var b = { firstName: 'Peter', lastName: 'Smith' };
var keepGoing = true;
for (var a in b) {
switch (true) {
case 1:
keepGoing = false;
break;
}
if (!keepGoing) break;
console.log('switch end');
}
console.log('for end');
example
Unfortunately, Javascript doesn't have allow breaking through multiple levels. The easiest way to do this is to leverage the power of the return statement by creating an anonymous function:
//code before
(function () {
for (var a in b) {
switch (something) {
case something:
{
//code inside
return;
}
}
}
}());
//code after
This works because return leaves the function and therefore implicitly leaves the loop, moving you straight to code after
As pointed out in the comments, my above answer is incorrect and it is possible to multi-level breaking, as in Chubby Boy's answer, which I have upvoted.
Whether this is wise is, from a seven-year-later perspective, somewhat questionable.
it depends on what you want to accomplish... one thing I commonly do is something like this:
//code before
for(var a in b)
{
var breakFor = false;
switch(something)
{
case something:
{
//code inside
breakFor = true;
break;
}
}
if (breakFor)
break;
}
//code after
You can tell which loop / switch to break.
function foo ()
{
dance:
for(var k = 0; k < 4; k++){
for(var m = 0; m < 4; m++){
if(m == 2){
break dance;
}
}
}
}
See this answer.
for(var i=0; i<b.length; i++) {
switch (something) {
case 'something1':
i=b.length;
}
}
When the iteration variable i reaches the end of the loop, it breaks. But one can force the iteration variable to reach the end of the loop.
Replace your switch with a series of if statements.
for (const a of b) {
if (something === someValue) {
// code inside
break; // break out of the for loop
} else if (something === someOtherValue) {
// etc.
}
}
I always find using conditional statements one of the easiest ways to control the code flow, at least conceptually.
var done = false;
//code before for loop
for(var a in b){
switch(switchParameter){
case firstCase:
//code inside
done = true;
break;
}
}
if(done)
break;
}
//code outside of for loop