Reputation: 502
I'm new using JavaScript and I'm trying to accomplish the follow exercise:
I have an array named bill
with 3 elements [124, 48, 268]
I want to call a function which calculates the tip depending on bill amount, less than $50 (percentage = 0.2), bill amount between $50 and $ 200 (percentage = 0.15) and bill amount over $ 200 (percentage = 0.1)
I have used the following code:
var bill = [124, 48, 268];
var percCalculation = function(amount) {
var percentage;
switch(amount) {
case (amount < 50):
percentage = .2;
case (amount >= 50 && amount < 200):
percentage = .15;
case (amount > 200):
percentage = .1;
}
return percentage * amount
}
var tipAmount = [percCalculation(bill[0]),
percCalculation(bill[1]),
percCalculation(bill[2])];
console.log(tipAmount);
However, I get the following results: (3) [NaN, NaN, NaN]
What is wrong with the code?
Upvotes: 0
Views: 42
Reputation: 1
your switch statement for the first amount, 124 would look like
var percentage = undefined; // implied value of undeifned
switch(124) {
case false: ......
case true: ....
case false: ....
}
return 124 * undefined; // this is Nan
Since no cases match 124, percentage never gets a value, and you get NaN as a result
So, you want to switch(true)
as only one case will ever be true
You also want to break
at the end of each case so the execution doesn't "fall through" to the next case
A little bonus, your function can be used as a callback to Array#map method - see bottom of snippet
var percCalculation = function(amount) {
var percentage;
switch(true) {
case (amount < 50):
percentage = .2;
break;
case (amount >= 50 && amount < 200):
percentage = .15;
break;
case (amount > 200):
percentage = .1;
break;
}
return (percentage * amount).toFixed(2) // returns a nice dollar and cents
}
var bill = [124, 48, 268];
var tipAmount = [percCalculation(bill[0]),
percCalculation(bill[1]),
percCalculation(bill[2])];
console.log(tipAmount);
// bonus ... use map to make your code "DRY"
var tip2 = bill.map(percCalculation);
console.log(tip2);
Please note: your logic would mean that if the amount is exactly 200, you will get a NaN result ... you need to either check <= 200 in second case or >= 200 in third case (as you've done for the 50 cutoff)
a brief note about the above usage of switch ... many languages have switch
but won't allow multiple case
with the same value - javascript does (not sure which other languages allow it) so, just be careful if using another language
Upvotes: 1
Reputation: 211740
Remember switch
cases "fall-through", as in keep executing until hitting a break
, return
or the end of the switch
, so:
var percCalculation = function(amount) {
var percentage;
switch(amount) {
case (amount < 50):
percentage = .2;
break;
case (amount >= 50 && amount < 200):
percentage = .15;
break;
case (amount > 200):
percentage = .1;
break;
}
return percentage * amount
}
var bill = [124, 48, 268];
var tipAmount = [percCalculation(bill[0]),
percCalculation(bill[1]),
percCalculation(bill[2])];
console.log(tipAmount);
While that fixes the fall-through problem, it exposes another more serious one
and that is the case
values are evaluated through matching, as in amount
must match one of the fully evaluted versions of those case
expressions,
so this looks like:
switch(amount) {
case true:
// ...
case false:
// ...
case false:
// ...
}
So it must be converted to if
statements:
var percCalculation = function(amount) {
var percentage;
if (amount < 50)
percentage = .2;
if (amount >= 50 && amount < 200)
percentage = .15;
if (amount > 200)
percentage = .1;
return percentage * amount;
}
var bill = [124, 48, 268];
var tipAmount = [percCalculation(bill[0]),
percCalculation(bill[1]),
percCalculation(bill[2])];
console.log(tipAmount);
Note you have an error in your logic, if amount
is 200
it will not match
anything and crash out using an undefined
value in multiplication. I prefer
to use more data-driven definitions, like this:
percentageForAmount = [
[ 200, 0.1 ],
[ 50, 0.15 ],
[ 0, 0.2 ]
];
Where you can look up values in that easily:
let rate = percentageForAmount.find((min, perc) => amount > min);
let percentage = rate[1];
It's also worth noting that it's generally better to define functions as functions, not as var
variables. There's no reason to redefine this each time you run it as nothing changes.
In other words:
function percCalculation(amount) {
// ...
}
Where you can call that as many times as you want with no additional overhead.
Upvotes: 1