lesson-cover

Go Back

Foundations of JavaScript

Functions

Have you ever had to do the same thing (like making rice) over and over again and thought to yourself, What if I wrote down instructions and had someone else do this?

Example: Instructions to make rice:

  1. Get a cup, fill it with rice
  2. Pour cup of rice into rice cooker
  3. Add 1 cup of water into rice cooker
  4. Make sure rice cooker is plugged in, and press the cook button

In the computer world, the above would be called a function.

A function is a set of instructions written to perform a specfic task.

A function is only executed when "something" invokes it (calls it).

Why use functions?

You can reuse code: Define the code once, and use it many times.

You can use the same code many times with different arguments, to produce different results.

Example function (This is a very bad way to write functions and is designed to only teach a concept. Do not write functions like this)

const greet = new Function('a', 'b', "return a + ' says, hello ' + b")
/*
In the above example, greet is a variable that is a function object.
*/
// Function objects can be run by putting () behind a function.
let c = greet('Ironman', 'Poodle') // c is "Ironman says, hello Poodle"
c = greet('base9', 'base2') // c is "base9 says, hello base2"

Let's break down the above example.

  • Parameters: Variables to hold the data when function run.

  • Run: Running a function means to execute it by adding a () to the end.

  • Arguments: Data you pass into the function when you run a function. Goes in between ()

  • Function body: Code that runs when a function is run. Notice how the function body is a string. After the Function Object is created, the string is converted into JavaScript code. In the example above, the code looks like the following:

    return a + ' says, hello ' + b
  • Return: The result of running the function. If the key word return is not in your function body, the function will automatically return undefined

Exercises

const fn = new Function('a', 'b', 'a + b')
const result = fn(23, 2) // what is result?
Answer
const fn = new Function('a', 'b', 'a + b')
const result = fn(23, 2) // result is undefined
// since nothing is returned
const fn = new Function('return 10')
const result = fn() // what is result
Answer
const fn = new Function('return 10')
const result = fn() // result is 10 since return 10 is executed
const fn = new Function('x', 'y', 'return x === y')
let result = fn() // what is result?
result = fn(9, 9) // what is result?
result = fn(9, 8) // what is result?
Answer
const fn = new Function('x', 'y', 'return x === y')
let result = fn() // what is result? result is true
// since both variables x and y have undefined values
result = fn(9, 9) // what is result? result is true
result = fn(9, 8) // what is result? result is false
const secret = new Function('a', 'b', 'a = a + 9; return a + b')
let b = secret // what is b?
let c = secret('base9', 'base2') // what is c?
c = b(10, 2) // what is c?
Answer
const secret = new Function('a', 'b', 'a = a + 9; return a + b')
let b = secret // b is a function object
let c = secret('base9', 'base2') // c is base99base2
c = b(10, 2) // c is 21

Function body written using strings is a very unpleasant way to write functions. There is an easier way.

let greet = new Function('a', 'b', "return a + ' says, hello ' + b")
let secret = new Function('a', 'b', 'a = a + 9; return a + b')
// Another way of creating the function object above without using strings
greet = function (a, b) {
return a + ' says, hello ' + b
}
secret = function (a, b) {
a = a + 9
return a + b
}

Function Return

When JavaScript reaches a return statement, the function will stop executing, return the returned value, and exit the function.

If the function was called from a statement, JavaScript will "return" to the calling statement and continue to execute the next statement. Any return value will be passed to the calling statement.

// Calculate the sum of two numbers, and return the result:
const sum = function (a, b) {
return a + b // Function returns the sum of a and b
const c = a - b // this statement will NEVER be executed
}
const x = sum(4, 3) // Function sum is called,
// returned value will be assigned to variable x.

Arrow Function

Another way to create a function object is to use an arrow function and its definition includes the arrow symbol =>. Notice the keyword function is missing. This is the preferred method today to create function objects. There are differences between function and () => {} and that difference will be covered in JS4.

**Syntax:**
const name = (parameter1, parameter2, parameter3) => {
// statements
}

To write an arrow function and store it into a variable called makeBasket, code this:

const makeBasket = () => {
const b = 500
return b
}

You can add instructions by putting them inside {}. In the above example, the function creates a variable and then returns its value. return is a keyword to stop the function and give a result.

const snitch = makeBasket // what is snitch?
const batter = makeBasket // what is batter?

= means the left side stores the right side. Since the right side is a function, both snitch and batter are functions. Note that they don't get the value 500, because we haven't run the function yet. We'll get to that soon.

This function is more complex than the functions we have done in the examples above:

const fn = (a, b) => {
let c = a + b
if (c > 2) {
c = 0
}
return c + 1
}
const result = fn(22, 1)

The above function is the preferred method today to create function objects.

Exercises

Write a function named solution that returns a value:

  1. A number (try to be creative; use some number operators like + - * / %).
Answer
const solution = () => {
return 5 + 2
}
  1. A string
Answer
const solution = () => {
return 'Hello' + !'Hello'
}
  1. A boolean
Answer
const solution = () => {
return !'Hello'
}
  1. A function
Answer
const solution = () => {
return () => {}
}

Running a Function

You can tell the computer to carry out the instructions in a function by simply adding () to the name of the function. For example, makeBasket() runs the makeBasket function in the example above.

Running a function has many synonyms. You might hear "running a function," "executing a function," or "calling a function."

const makeBasket = () => {
return 500
}
const snitch = makeBasket // snitch is a function
const batter = makeBasket // batter is a function
const result1 = makeBasket() // result1 is 500
const result2 = snitch() // result2 is 500
const result3 = batter() // result3 is 500
/*
IMPORTANT
result1 stores the returned value of running the makeBasket function
result2 stores the returned value of running the snitch function
result3 stores the returned value of running the batter function
*/

Important: By storing the returned value of running the function, we can now use the result1, result2, and result3 variables at a later time.

Exercises

Note that not all these functions exist, so you don’t need to try running them on your computer. Just write the statements to run the functions.

  1. Run a function called alert
Answer

alert()

  1. Run a function called app.get
Answer

app.get()

You can make up any functions you want. Assume someone made up app.get function - all you have to do is put () behind the function to run it.

  1. Run a function called console.log
Answer

console.log()

  1. Run a function called Object.keys
Answer

Object.keys()

const keeper = () => {
return 5
}
let snitch = keeper // what is snitch?
snitch = !keeper // what is snitch?
snitch = !keeper() // what is snitch?
Answer
const keeper = () => {
return 5
}
let snitch = keeper // function
snitch = !keeper // false: functions are truthy, so !truthy is false
snitch = !keeper() // false: now we run the function and get 5; !5 is false

Examples

Functions are the most important concept in JavaScript (more on that later), so here are more examples.

Note: You must step through each line like a computer. Keep in mind that values of variables change constantly.

let points = 0
const igor = () => {
points = points + 1
return points
}
let luna = igor // what is luna?
luna = igor() + igor() // what is luna?
Answer
let points = 0
const igor = () => {
points = points + 1
return points
}
let luna = igor // luna is a function
luna = igor() + igor() // 3, because 1 + 2
/*
Be careful: Every time igor is executed, the value of points get updated.
*/

If a function does not return anything, undefined is returned. undefined is a JavaScript primitive data type. Note that undefined is falsy.

const carrotCakeRecipe = () => {}
let snitch = carrotCakeRecipe() // snitch is undefined
snitch = !carrotCakeRecipe() // what is snitch?
Answer
const carrotCakeRecipe = () => {}
let snitch = carrotCakeRecipe() // undefined, because carrotCakeRecipe returns nothing
snitch = !carrotCakeRecipe() // true, because undefined is falsy
const work = () => {
const blah = 5 + 8
}
const wage = work() // what is wage?
Answer
const work = () => {
const blah = 5 + 8
}
const wage = work() // wage is undefined

You can call functions within other functions:

let people = ''
const igor = () => {
people = people + ' muggle '
return people
}
const solution = () => {
igor()
igor()
igor()
}
const luna = solution() // what is luna?
// what is people?
Answer
let people = ''
const igor = () => {
people = people + ' muggle '
return people
}
const solution = () => {
igor() // after this function runs, people has the value: " muggle "
igor() // after this function runs, people has the value: " muggle muggle "
igor() // after this function runs, people has the value: " muggle muggle muggle "
}
const luna = solution() // luna is undefined
// people is " muggle muggle muggle "
Thought process

Step by step of how an engineer would think through the problem above:

  1. people takes the value ''
  2. igor is a function
  3. solution is a function
  4. luna is.... what ever solution returns. Lets run solution
  5. Gotta run igor. people is ' muggle'
  6. Gotta run igor. people is ' muggle muggle'
  7. Gotta run igor. people is ' muggle muggle muggle'
  8. solution doesn't have the word return. So it returns undefined
  9. luna is undefined.

An arrow function can return anything! In the previous examples, you have seen functions returning a string, a number, or undefined.

Can you Write an arrow function named solution that returns another arrow function?

Answer
const solution = () => {
return () => {}
}

Here is another fun example:

let people = ''
const igor = () => {
return () => {
people = people + ' muggle '
return people
}
}
const luna = igor() // luna is a function
let lovegood = luna() // lovegood has a value of " muggle "
lovegood = luna() // lovegood has a value of " muggle muggle "
// because people was changed to " muggle " from
// running the previous function.

Exercises

  1. Write an arrow function named solution that runs a function called console.log three times and return a number.
Answer
const solution = () => {
console.log()
console.log()
console.log()
return 5
}
  1. Write an arrow function named solution that returns a function. When the returned function is called, console.log will run three times.
Answer
const solution = () => {
return () => {
console.log()
console.log()
console.log()
}
}

Parameters / Arguments

Sometimes, instructions might need requirements. When you write out instructions for cooking rice, you need to make sure you have both rice and a rice cooker.

In the computer world, some functions might need additional data to run. For example, the function add2 would need a number first so it can add 2 to the original number.

Parameters are inputs into a function. When writing a function, all parameters are simply made-up variable names that will take the value of the respective data when the function is called.

When you run a function, the data you pass in are called arguments.

const lucius = dobby => {
return dobby + 2
}
let james = lucius(5) // james is 7, because lucius returns 5 + 2
james = lucius(5) === lucius(3) + 2 // what is the value of james?
Answer
const lucius = dobby => {
return dobby + 2
}
let james = lucius(5) // james has value of 7, because lucius returns 5 + 2
james = lucius(5) === lucius(3) + 2 // james has true value, because 7 === 5 + 2
let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky
return points + fluffy
}
// draco is a function that takes in 3 parameters: x, y, and z
const malfoy = draco(1, 2, 3) + draco(3, 2, 1) // what is the value of malfoy?
// what is the value of points?
Answer
let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky
return points + fluffy
}
// draco is a function that takes in 3 parameters: x, y, and z
const malfoy = draco(1, 2, 3) + draco(3, 2, 1)
// draco(1,2,3) -> points now has 3 (was 0 before); draco returns 3 + 3
// draco(3,2,1) -> points now has 5 (was 3 before); draco returns 5 + 1
// (points is no longer 3)
// malfoy is 6 + 6, which is 12
// points is now 5

You can pass in anything to a function! Below is an example of passing a function as an argument into another function:

const grindle = () => {
return 10
}
let wald = cast => {
return cast()
}
let grindlewald = wald(grindle)
// Explanation for the above:
// We are passing the function **grindle** as an argument into the function **wald**
// **grindle function** is the input parameter **cast** for **wald function**
// **wald** returns the result of running the **cast function**, which is 10
// Therefore, grindlewald has the value of 10
wald = cast => {
cast()
}
grindlewald = wald(() => {
return 10
})
// In the above example, we are passing a function as an argument into
// the function wald (like the previous example).
// However, wald is a function that does not return anything,
// so it will return undefined by default.
// Therefore, grindlewald is undefined.

In this example, we will call the JavaScript setTimeout method. The setTimeout method calls a function or executes some code once after a specified delay (in milliseconds).

The syntax is : setTimeout(function, milliseconds ).

Note: use setTimeout() to repeat the execution continuously.

const invisible = () => {
setTimeout(() => {
return 100
}, 1000)
}
const cloak = invisible() // what is cloak?
Answer
const invisible = () => {
setTimeout(() => {
return 100
}, 1000)
}
const cloak = invisible() // cloak is undefined
// invisible function first runs the setTimeout function with
// 2 arguments: function and 1000
// invisible function returns undefined

BEWARE: Parameters MUST have variable names.

Exercises

HINT: When you write a function, it does not matter what data types the parameters are. Many of the following write a function questions should have the same answer!

Write a function named solution that has:

  1. a string parameter, and returns a function

  2. a number parameter, and returns a function

  3. a boolean parameter, and returns a function

  4. a function parameter, and returns a function

Answer
const solution = one => {
return () => {}
}
  1. 2 parameters (a function and a number), and returns a function
Answer
const solution = (one, two) => {
return () => {}
}
If your are confused...
const solution = (() => {}, 4) => {}
// <-- If your solution looked anything like this for number 5...
//
/*
... remember that when writing a function, you cannot use real values.
You must use variable names as parameters.
solution = (a, b) => {
.
.
}
*/

Part 2:

  1. Run a function named console.log and pass in 2 arguments (2 strings)
Answer
console.log('hello', 'world')
  1. Run a function named app.get and pass in 1 argument (an arrow function)
Answer
app.get(() => {})
  1. Run a function named setTimeout and pass in 2 arguments (an arrow function and a number)
Answer
setTimeout(() => {}, 1000)

Functions with Conditional Behavior

Remember that to execute code conditionally, you use an if statement, which looks like the following:

if (<condition>)
{instructions to run}

A truthy or falsy value goes inside the parentheses.

The code inside the curly brackets will execute if the value inside the parentheses is truthy. Below are a few examples with functions:

const remember = events => {
if (events > 5) {
return 'well done'
}
return 'fail'
}
let result = remember(0) // result will be "fail"
result = remember(20) // result will be "well done"
const newt = x => {
if (x === 5) {
return 13
}
return x + 1
}
let tonks = newt(3) // what is the value of tonks?
tonks = newt(11) // what is the value of tonks?
tonks = newt(5) // what is the value of tonks?
Answer
const newt = x => {
if (x === 5) {
return 13
}
return x + 1
}
let tonks = newt(3) // 4
tonks = newt(11) // 12
tonks = newt(5) // 13
const neville = (long, bottom) => {
if (long > bottom) {
long = long + 3
}
return long
}
let hermione = neville(4, 5) // what is hermione?
hermione = neville(9, 2) // what is hermione?
Answer
const neville = (long, bottom) => {
if (long > bottom) {
long = long + 3
}
return long
}
let hermione = neville(4, 5) // 4
hermione = neville(9, 2) // 12
let points = 3
const charlie = (arthur, percy) => {
points = points + 1
if (arthur > percy) {
return points
}
return arthur + points
}
const hedwig = charlie(4, 5) || charlie(9, 2) // what is the value of hedwig?
const nick = charlie(9, 2) // what is the value of nick?
Answer
let points = 3
const charlie = (arthur, percy) => {
points = points + 1
if (arthur > percy) {
return points
}
return arthur + points
}
const hedwig = charlie(4, 5) || charlie(9, 2) // 8
// First the computer will run charlie(4,5), which returns 8
// Since 8 is truthy, the computer does not do the right side of ||
// When charlie ran, the points variable was updated to 4
const nick = charlie(9, 2) // nick is 5.
let points = 3
const charlie = (arthur, percy) => {
points = points + 1
if (arthur > percy) {
return points
}
return 0
}
const hedwig = charlie(4, 5) || charlie(9, 2) // what is the value of hedwig?
const nick = charlie(9, 2) // what is the value of nick?
Answer
let points = 3
const charlie = (arthur, percy) => {
points = points + 1
if (arthur > percy) {
return points
}
return 0
}
const hedwig = charlie(4, 5) || charlie(9, 2) // 5
// First the computer will run charlie(4,5), which returns 0
// and points is updated to 4.
// Since 0 is falsy, the computer runs the right side of ||
// hedwig takes the return value of charlie(9,2), which is 5
const nick = charlie(9, 2) // nick is 6, because charlie(9,2) returns 6

Exercises

  1. Write an arrow function named massiveOrSmall that adds 2 numbers and returns "massive" if the sum is over 100; otherwise returns "small".
Answer
const massiveOrSmall = (a, b) => {
if (a + b > 100) return 'massive'
return 'small'
}
  1. Write a function named sumOrTen that takes in 2 numbers. It should return 10 if both numbers are bigger than 10; otherwise it should just return their sum.
Answer
const sumOrTen = (a, b) => {
if (a > 10 && b > 10) {
return 10
}
return a + b
}
  1. Write a function named combineIfOver42 that returns either two strings combined or the empty string, depending on whether an input number is over 42.

    Sometimes when you're asked to write a function, if a quick description isn't enough to make the assignment, you'll be given some examples of how it should work:

    combineIfOver42('Harry ', 'Potter', 23) // returns ""
    combineIfOver42('Ron ', 'Weasley', 43) // returns "Ron Weasley"
Answer
const combineIfOver42 = (a, b, c) => {
if (c > 42) {
return a + b
}
return ''
}
  1. Write a function named compareStrings that returns true if two strings are equal and false if they're not.
Answer
const solution = (a, b) => {
return a === b
}

Execution Context

Let's explore what happens when the following function is run, step by step.

Before the computer runs your code, it first creates a box to store all the variables. We call this box the global execution context.

Every time the computer runs a function, it will create a new box inside the box where the function was created (after you understand this, replace the word box with execution context). Let's use the following example:

Before the computer runs the code, it first creates a global execution context.

let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky
return points + fluffy
}
const malfoy = draco(1, 2, 3)
const mal2 = draco(3, 2, 1)

Line 1 - create a global variable named points. Line 2 - create a global variable named draco.

let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky
return points + fluffy
}
...
...

Line 6 - Run the draco function with 1,2,3.

Remember, every time a function is run, a box (local or functional execution context) is created. Since there are 3 parameters, this local execution context has 3 local variables.

let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky
return points + fluffy
}
const malfoy = draco(1,2,3) // line 6
...

Line 3: Inside the draco function, the global variable points in the global execution context is updated to 3.

let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky // line 3
...
}
const malfoy = draco(1,2,3)
...

Line 4: draco function returns 6 - Function is done, line 6 continues, and malfoy takes the value of 6. The local execution context for draco function is removed and is no longer accessible.

let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky
return points + fluffy // line 4
}
const malfoy = draco(1,2,3) // line 6
...

Line 7: Run draco function with 3,2,1

Remember, every time a function is run, a new local execution context is created. Since there are 3 parameters, this new local execution context has 3 local variables:

let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky
return points + fluffy
}
const malfoy = draco(1, 2, 3)
const mal2 = draco(3, 2, 1) // line 7

Line 3: Inside the draco function. The global points variable is updated to 5.

let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky // line 3
...
}
const malfoy = draco(1,2,3)
const mal2 = draco(3,2,1)

Line 4: draco function returns 6 - Function is done, line 7 continues, and mal2 takes the value of 6

let points = 0
const draco = (kreacher, winky, fluffy) => {
points = kreacher + winky
return points + fluffy // line 4
}
const malfoy = draco(1, 2, 3)
const mal2 = draco(3, 2, 1) // line 7

Done! Before the execution of the code ends, the global execution context has the following global variables:

points: 5
draco: function
malfoy: 6
mal2: 6

Summary

Words you must know by heart:

variable, number, string, boolean, function, parameters, arguments, execution context, global

Concepts you must know:

  • How to create a variable (using const and let)
  • When truthy / falsy properties are important
  • What it means to write a function and what it means to run a function
  • What return does
Master your skill by solving challenges

Complete the rest of JS0 challenges

Edit this page on Github