Parameters and return
Problem
One receipt, different totals
You want a function that prints the last line of the receipt: "Total: €…". But the total is different for every order.
The functions from the last lesson always print the same thing. A function printTotal() has no way to know the total. You do not want a separate function for every total either. You need a way to pass the total to the function when you call it.
The idea
Parameters: what the function gets
In the parentheses, write a name for what the function expects. That is a parameter. Inside the function it is an ordinary variable.
When you call it, you put the value in the parentheses. That value is called an argument.
function printTotal(total) { console.log(`Total: €${total}`);}
printTotal(12.5);printTotal(4.2);Total: €12.5Total: €4.2total is the parameter. 12.5 and 4.2 are the arguments. There is one function, and it prints different totals.
You do not write a type before the parameter: JavaScript does not check what you pass. If you pass text instead of a number, the function prints it without complaining. That is why the parameter's name has to say clearly what is expected.
If there are several parameters, you separate them with commas. The arguments are passed in the same order.
Try it
By position, not by name
What will the program print?
function printLine(item, qty) { console.log(`${item}: ${qty} pcs`);}
const coffee = "Coffee";const qty = 3;printLine(coffee, 2);Arguments are matched to parameters by position: the first one to item, the second one to qty. The variable qty outside has nothing to do with the parameter qty, even though they have the same name.
Problem
Why did the price not go down?
You have written a function for a 10% discount and called it:
function applyDiscount(price) { price = price * 0.9;}
const price = 100;applyDiscount(price);console.log(price); // 100100The price is still 100. The function gives no error, and yet the discount is not there. Where did it go?
See it
The function gets a copy
function applyDiscount(price) { price = price * 0.9;}
const price = 100;applyDiscount(price);console.log(price); // 100Step by step, in words
- In the program there is a variable price = 100.
- You call applyDiscount(price): new memory is set aside for the function.
- The value is copied into its parameter price.
- The function lowers its copy: 100 * 0.9 = 90.
- The function ends and its memory goes away, along with the copy.
- And price in the program is still 100.
When you call it, the function does not get the variable price itself, but a copy of its value. It lowers the copy. When the function ends, its memory goes away, and the copy goes with it. This is called pass by value.
The two variables have the same name (price) on purpose: that is exactly what confuses people in practice. The name does not matter. Every function has its own variables.
More precisely, if you are curious
In JavaScript, arguments are always passed by value. With arrays and objects, what gets copied is the link to them, so changes made inside the function are visible outside too:
function addItem(items) { items.push("milk");}
const cart = ["bread"];addItem(cart);console.log(cart);[ 'bread', 'milk' ]We will look at objects in the "Classes and objects" module.
The idea
return: the function returns a result
The fix is for the function to return the new price. In the body you write return and the value. You do not write a type for the result: function is the same whether or not the function returns something.
function applyDiscount(price) { return price * 0.9;}
let price = 100;price = applyDiscount(price);console.log(price); // 90Step by step, in words
- In the program: price = 100.
- You call applyDiscount(price): memory is set aside for the function.
- The value is copied into the parameter price.
- return price * 0.9: the result is 90.
- The result goes back to the program and is stored in price.
- Now price in the program is 90.
The call applyDiscount(price) is now a value. You can store it in a variable (as here), print it or calculate with it.
More precisely, if you are curious
- A function without
returnstill returns something:undefined, the "nothing" value. If you print the result of the first version, which only lowered its own copy, that is exactly what you see:
function applyDiscount(price) { price = price * 0.9;}
console.log(applyDiscount(100));undefined- You can also write
returnwith no value. It just ends the function.
- A function can return several values at once in an array, and in the call you split them into separate variables with the brackets
[ ]:
function getLimits() { return [1, 10];}
const [low, high] = getLimits();console.log(low, high);1 10Try it
What is the result?
The function works out a 20% VAT on the price. What should go in the blank so that whoever calls it gets the result?
function vat(price) {
price * 0.2;
}return: without it the function works out price * 0.2 and throws the result away, and the call gives undefined.Try it
Returned, but lost
What will the program print?
function reserve(seats) { seats = seats - 2; console.log(`inside: ${seats}`); return seats;}
const seats = 10;reserve(seats);console.log(`outside: ${seats}`);The function changes its copy and returns 8, but nobody stores the result. To keep it, you need seats = reserve(seats);.
Then seats has to be declared with let, because its value changes.
The idea
return ends the function
The shop does not charge for delivery on orders of €50 or more. Otherwise delivery is €4.99:
function shippingCost(total) { if (total >= 50) { return 0; } return 4.99;}
console.log(shippingCost(62.0));console.log(shippingCost(18.5));04.99As soon as it reaches return, the function ends right away. That is why at €62 the second return does not run, and we do not need an else.
A function with a result has to return a value on every path. But JavaScript does not check this. If you remove the last line, the program runs, and for an order of €18.50 the function reaches its end without a return and returns undefined:
function shippingCost(total) { if (total >= 50) { return 0; }}
console.log(shippingCost(62.0));console.log(shippingCost(18.5));0undefinedThere is no error, so a slip like this is hard to catch. Watch the output and try every path through the function.
Try it
Find the bug
Club members get a 10% discount, and everyone else pays the full price. But everyone gets the discount. Which line is the bug on?
Pick the line with the bug.
The last return is for people who are not members: they pay the full price, return price;.
Exercise
Functions that calculate
Solve the tasks in your editor. Each function gets what it needs as parameters and returns the result. The printing happens outside the functions, in the lines below them.
1. Average. The function average(values) returns the average of the numbers in the array. Below it, read from the keyboard how many numbers there are, then the numbers themselves.
51015202530Average: 202. Prime number. The function isPrime(n) returns whether the number is prime (divisible only by 1 and by itself). For 7 it returns true, for 12 false.
3. Temperatures. The functions toFahrenheit(c) and toCelsius(f). F = C · 9 / 5 + 32. Read a temperature and a unit (C or F) and print the converted one.
100C100 C = 212 F4. Calculator. The function calculate(a, b, op) returns the result for +, -, * or /. The operation is chosen with if.
105+10 + 5 = 155. A triangle with a parameter. We promised it in the last lesson. The function printTriangle(height) prints a right triangle of asterisks with height height. For 3:
** ** * *More precisely, if you are curious
In JavaScript, / always gives a decimal number, so 5 / 9 is 0.5555…, not 0 as in Java and C#. If you need the whole part, write Math.trunc(a / b):
console.log(5 / 9);console.log(Math.trunc(7 / 2));0.55555555555555563Exercise
Functions for arrays
Each task is one function that gets an array (or a word) and returns a result. At the end, put them all together in one program.
sum,sumEvenandsumOdd: the sum of all the numbers, of the even ones and of the odd ones in the array.reverse: returns a new array with the numbers in reverse order.maxandmin: the largest and the smallest number.isPalindrome(word): whether the word reads the same forward and backward.sumDiagonalsandsumDiagonalsOnce: the sum along both diagonals of a square matrix, with the center element counted twice and once.- All together: for the array
[1, 2, 3, 4, 5], the number 7 (withisPrimefrom the card above), the words "level" and "ABCDE" and the 3 × 3 matrix with the numbers from 1 to 9.
Sum: 15, Even: 6, Odd: 9Reversed: [5, 4, 3, 2, 1]Max: 5, Min: 17 is prime: truelevel: true, ABCDE: falseSum with repeats: 30, Sum without repeats: 25Test