Open CheatSheet Back To List Next Tutorial

Functions

Intro

  • In this tutorial we will cover how Functions work in JavaScript.

  • It is recommended that you follow along with each section below. Paste or type the code into your own JavaScript file and view the variable or expression values either with console.logs or using the VS Code Debug sidebar. 

  • The example code for the entire tutorial series is at github.com/LearnByCheating/javascript-tutorial. There is a separate file or folder for each tutorial, including the To-Do List example project. The Readme file has instructions on how to run the code.


1. The function declaration: parts of a function

  • We will start with function declarations. 
  • Functions are self contained blocks of code that accomplish a specific task. 
  • Functions are not executed until they are called. 

Format:
function name(parameters) { 
  statements;
  return statement;


name(arguments);

  • A function declaration starts with the keyword function, followed by the function name.
  • Parameters: Then comes parentheses that may contain parameters. Parameters are values are passed into the function when it is called. Parameters are like variables that can be used in the function statements.
  • Function Body: Inside the curly braces are the statements of code that get executed as a block of code. 
  • Return statements: 
    • Functions always return a result. 
    • The last statement in a function starts with the keyword "return" followed by whatever you want the function result to be. 
    • If there is no return statement, the function returns undefined.

Functions are callable:
  • What makes functions unique is the code block is not executed until the function is called.
  • You call the function by entering the function name followed by parentheses that may contain arguments.
  • Arguments: In the parentheses you can pass in values for the function's parameters. These values are called arguments. You will often hear the terms parameters and arguments used interchangeably. 
    • Parameters are the placeholders for the values that get passed to the function.
    • Arguments are the actual values that get passed to the function when it is called. 

Example: function that adds two numbers together
function add(x, y) {
  const res = x + y;
  return res;
}
let res = add(5, 3); // returns 8

  • The above example function has two parameters, x and y. 
  • The function body adds the two parameter value together, the returns the result.
  • We call the function passing in two arguments 5 and 3. 
  • We assign the function's return value of 8 to the variable res. 


2. Function Hoisting

Function declarations are hoisted to the top of the script or the function they are contained in.
That means you can call the function before it is declared.

Example:
res = add1(10); // returns 11
function add1(x) {
  const result = x + 1;
  return result;
}

In the above example we are calling the add1 function before it is declared, and it will work. We passed in 10 as the argument, the function adds 1 to it and returns 11.


3. Global Scope

In the browser, the global object is called window. It holds all the built-in JavaScript objects and Web APIs that we use in our code.
Functions declared outside of any other functions or objects are attached to the global object. When we declared the add1 function it was attached to the global object:
window.add1(10); // returns 11

The global object is implicit so you can access it without explicitly chaining it to window. 
Anything attached to the global object has a global scope, meaning it can be accessed anywhere in your code.
add1(20); returns 21.


4. Function Scoped

Function declarations are function scoped. That means if a function is declared within another function it is not accessible outside that function. 

Example:
function mathFunctions() { 
  function add2(x) { return x + 2; } const res = add2(5);
} console.log(res); // ReferenceError add2(10); // ReferenceError

In the above example we declare a function called mathFunctions.
Inside that function we declare another function named add2 and a variable named res.
The add2 function and the res variable are not accessible outside the scope of mathFunctions.

If you try to access the res variable or call the add2 function outside it's scope you will get a reference error. 


5. Function declarations are not block scoped

Functions declared in non-function blocks like if statements are still accessible outside the block.

Example:
const x = 2
if (x > 0) {
  function add3(x) {
    const res = x + 3;
    return res;
  }
}
add3(10); // returns 13

The add3 function is declared inside an if statement. 
If you call it from outside the if statement it will work fine. add3(10) returns 13.


6. Arrow functions

Arrow Functions were introduced in 2015 with the release of ES6.
There are some syntax and other differences between arrow functions and function declarations:

Format:
const functionName = (parameters) => {
  statements;
  return statement (if you are returning something);
}

  • From a syntax perspective, the function keyword is removed and replaced with a fat arrow.
  • The function name is removed, making it an anonymous function. Instead the function is assigned to a variable and follows the rules of the variable. It is common practice to use a const variable. 
  • With a const there is no hoisting. So arrow functions can't be called before they are declared. 
  • Const variables are block scoped, not function scoped. So arrow functions inside an if statement are not accessible outside the if statement.
  • Const variables are not attached to the global object.

Example:
const add4 = (x) => {
  const result = x + 4;
  return result;
}
add4(10); // returns 14


7. Arrow functions: single statement arrow functions

Arrow functions allow a shortened syntax for single statement functions.
Format:
const functionName = (parameters) => statement;
functionName(args);

Example:
const add5 = (x) => x + 5;
add5(10); // returns 15

They go on a single line and you omit the curly braces and the return keyword.
The add5 function is an example of a single statement arrow function.
You call it the same way as any other function. Calling add5(10) returns 15.


8. Immediately Invoking Function Expressions

Immediately invoking function expressions are anonymous functions that call themselves. They are a function declaration and function call in one. 

These can be used to segregate the content into its own function scope. They are not used often.

Format:
(function (params) { 
  statements; return statement (if any)
}(args));

  • Anonymous means the function has no name.
  • Instead of calling the function by a name, you place the parentheses and any arguments directly after the function.
  • And you wrap the whole thing in parentheses making it one big expression.

Example:
(function (x) { 
  const result = x + 6;
  return result;
}(10));

  • In the above example our IIFE adds 6 to the argument. 
  • The argument in this case is 10.
  • The function return value is 16.


9. Methods (functions that are properties of objects)

  • Objects are a collection of properties.
  • You can think of properties as variables that are attached to an object. 
  • Methods are properties that are functions.

Format:
const obj = {
  propName1: propValue,
  propName2: propValue,
  methodName: function() { statements; },
}; obj.methodName(arguments);

Example:
const user = {
  name: 'Joey',
  age: 22,
  addYear: function() { this.age = this.age + 1 },
};
user.addYear(); user.age; // 23

  • Above is an example of an object named user.
  • It has properties for name and age.
  • The user.age property value is 22.
  • And it has a method called addYear that when called, increases the age by 1.
  • You call the method by chaining it to the object name. Meaning you place it after the object name separated by a dot.
  • At the bottom we called the addYear method by chaining it to the user object. 
    • user.addYear();
  • The method increases the user.age value by 1. It works like any other function.
    • function() { this.age = this.age + 1 }
  • The keyword this means the current object. So setting this.age sets the age property of this user object. Then if we access user.age; it will give us the new value 23.


10. JavaScript built-in object methods

The JavaScript programming language uses built-in global objects that contain properties and methods that you can access anywhere in your code. You chain built-in methods to values. The type of value determines what built in methods can be called on it. 
String values can call methods from the String.prototype object.
Boolean values can call methods from the Boolean.prototype object.
The same holds for numbers, objects, arrays, dates, regular expressions, promises, etc.

Example:
const str = 'some text'
str.toUpperCase(); // returns SOME TEXT

For example the String.prototype global object has methods for working with strings. 
If you chain the toUpperCase() method to a string value, it will apply the method and return a string with all upper case letters.


11. Parameters and arguments: too many and too few

If you pass in more arguments than the function accepts, the extra arguments are ignored.

Example:
const add5 = (x) => x + 5;
add5(10, 11, 12); // returns 15

In the above example, the add5 method only has one parameter yet we are passing in three argument values. The function accepts the first argument, ignores the extra arguments, and returns a result of 15.

If you don't pass in enough arguments, the missing values are set to undefined.

Example:
function add(x, y) {
  const result = x + y;
  return result;
}
add(10); // returns NaN

The above example calls the add function which takes two parameters, adds them together, and returns the result.
But we are only passing in one argument, so the missing parameter is set to undefined.
If you try to add undefined to a number it will return the NaN value which is a keyword meaning Not a Number.


12. Default parameters

Default parameters were introduced in 2015 as part of ES6.
You can set a default value for a parameter by adding an equal sign then the value when listing the parameters.

Format:
function functionName(param1, param2 = defaultVal) { statements }

Example:
function multiply(x, y = 0) {
  const result = x * y;
  return result;
}
multiply(10); // returns 0

The above example defines a function called multiply that has two parameters. The second parameter sets a default value of 0. That way if only one number is passed in it will multiply that by 0 instead of trying to multiply it by undefined.

Calling multiply(10) will return 0 since the missing y parameter defaults to 0. 10 x 0 is 0. 


13. Rest parameters

Rest parameters were also introduced in 2015 with ES6.
Rest parameters can take an indefinite number of arguments and stores them in an array.
The rest parameter must be the last parameter and it starts with three dots.

Format:
const funcName = (param1, ...restParamName) => {
  restParamName.forEach((param) => console.log(param));
}
funcName(arg1, [arg2, arg3,...]);

Example:
const highScore = (name, ...scores) => {
  const sorted = scores.sort((a,b) => b - a);
  return `${name}'s highest score is ${sorted[0]}.`
}
res = highScore('Judy', 75, 82, 94, 72, 88);

Above is a function called highScore. 
The first parameter is name, and the next parameter is a rest parameter called scores.
It takes all the rest of the arguments passed in and puts them in an array called scores.
In the function body we use the array sort method to sort the numbers highest to lowest.
Then for the return value we return a string that includes the name that was passed in, and the first value from our sorted scores array, which is the highest value:
"Judy's highest score is 94."


14. Variable scope

Now we will cover variables as they relate to functions.
Functions have access to all variables and functions defined in the global scope.
They have access to variables declared before it in the outer scopes. 
And they have access to functions declared in the outer scopes. 

Variables declared within a function are local variables and can't be accessed from outside the function.

Example:
let res = 0;
function add6(x) {
  const y = 6; // local variable
  res = x + y; // Assign value to the res variable from the outer scope
}
add6(10);
res; // value is 16 y; // throws ReferenceError: y is not defined

  • The res variable was declared in the outer script's scope so we have access to it in the add6 function.  we can set a new value for it in the function.
  • add6:
    • The add6 function has a parameter called x. The value for x is the argument value that is passed in when the function is called, which is 10 in the above example. The parameter x behaves like a local variable in the function scope.
    • The variable y is declared in the adAdd6 function so it is scoped to that function.
    • The x parameter and y variable are added together. The result is assigned to the res variable.
  • Outside the function, after it is called the res value is now 16.
  • When we try to access the y variable we get a ReferenceError. We cannot access y outside the function.


15. Variable scope: shadowing

Variable Shadowing is where you redeclare a variable from a higher scope in your function. This overwrites the variable in the local scope only. It does not affect the original variable in the outer scope. 
Style guides recommend not shadowing variables because it could lead to confusion as to which version of the variable you are accessing.

Example:
const num = 10;
function add7(x) {
  const num = 7;
  const res = num + x;
  return res;
}
add7(10); // returns 17 num; // value is 10

The add7 function above redeclares the num variable assigning it a different value.

Calling add7(10) returns 7 + 10 which is 17. In the function's local scope, num is redeclared and set to 7.
But in the outer scope, num is still set to 10. 


16. Arguments: primitives are passed by value

Primitive value arguments are passed by value, while objects are passed by reference.

The most commonly used primitive data types are strings, numbers, booleans, null and undefined.
When you pass a primitive value as an argument to a function you are passing the value itself.
From there you can change it and it doesn't affect the original value.

Example:
let age = 22;
function changeAge(age) {
  age = age + 1;
  return age;
}
const newAge = changeAge(age); // returns 23 age; // returns 22

  • In the above example we declare a variable named age and set it to 22.
  • In the function we called the parameter age as well. Parameters are treated as local variables in the function.
  • Then we reset the age parameter value to age + 1 which is 23. So changeAge(age) returns 23.
  • The original age variable value did not change though. It is still 22. 


17. Arguments: objects are passed by reference

While primitive arguments are passed by value, object arguments are passed by reference.
That means we pass in an argument that points to the object's location in memory, not the object itself.

Example:
const user = {
  name: 'Joey',
  age: 22
};

function changeObj(obj) {
  obj.age = obj.age + 1;
  return obj;
}
const updatedUser = changeObj(user); user.age; // returns 23 updatedUser.age; // returns 23
user === updatedUser; // is true

When we call the changeObj function we are passing in the user object as the argument into the obj parameter.
The obj parameter now holds the reference to the user object. The fact that we gave it a different name makes no difference.
We add 1 to the age property value, then return the object.
The user object age value has changed.

And if we compare the return value of the function and our original user object they are equal. They both reference the same object in memory.


18. Return statement

JavaScript functions always return a value, even if that value is undefined.
The return statement causes the function to stop executing and returns the value of its expression to the caller.

Example:
let res = 'Initial value';
function unreachableCode() {
  res = 'This line is reachable.';
  return;
  res = 'This line is unreachable';
}
unreachableCode(); res; // returns 'This line is reachable.'

  • The res variable is declared outside the function.
  • The function unreachableCode above starts out with a statement that sets the res variable to a string.
  • The next line is the return statement, followed by another line that sets res to a different string.
  • Only the line before the return statement gets executed so the res value becomes: "This line is reachable." Everything after the return statement is ignored.


19. Return statement implicit in one-line arrow functions

We looked at single line arrow functions earlier with their short syntax.
They have an implicit return statement, so you leave out the return keyword, and leave out the curly braces.

Format:
const funcName = (params) => statement

Example:
const add9 = (x) => x + 9; 
add9(10); // returns 19


20. No return statement. Side effect only

Functions can exist to produce a side effect only with no return statement. In these cases the function just returns undefined.  

Example:
function add10(x) {
  console.log(x + 10); // logs 20 to the console
}
add10(10); // returns undefined

  • The add10 function above does not have a return statement.
  • If you call the add10 function it logs 20 to the console, but the return value is undefined


21. The Function global object: name and length properties

Lastly, functions are a type of object and like other JavaScript constructs there is a Function global object with some properties you can apply to your functions if you need them.

Example:
function add10(x) {
  return x + 10;
}
add10.name; // value is "add10"
add10.length; // value is 1

The name property returns the name of the function as a string.
Chain it to the function and it will return the name "add10".
The length property will return the number of arguments expected by the function. In this case 1.


Conclusion


The topics in this tutorial correspond with the JavaScript CheatSheet Functions category. Make sure you understand each topic so you can refer back to the CheatSheet when working on your own projects.

If you have the CheatSheet desktop app and downloaded the JavaScript CheatSheet, then go through the flashcards for this category to the point where you can answer them all in order and shuffled.
Open CheatSheet Back To List Next Tutorial