Basics of Functions in JavaScript

All the Basics of Working with & Writing Your Own Functions in JavaScript.

Functions are one of the most important fundamentals of JavaScript. Event Handling, Callbacks, Data Manipulation, Constructor & Factory Functions are just some examples of how Functions are used in JavaScript.

This article will help you understand everything there is about Functions in JavaScript.

What is a Function?

A Function can be described as a Sub-Program or a Block of reusable code. Like a regular JavaScript program, a function is composed of a sequence of statements called the function body.

A Function can take in inputs through Parameters & provide an output using return statements.

How to write your Functions?

Defining a Function:

Functions are created using the function keyword followed by a Function Name. A Function Name follows the same naming rules as Variables, you can refresh your memory about Naming Convention Here.

After the Function Name, you need a pair of Parenthesis (more about these later), & finally the Function body within a pair of curly brackets or braces {}.

Here is an example of a function called greet:

function greet() {
    console.log("Hello World!");
}

Once defined, a function can be executed by using the Function Name followed by a pair of parentheses. This process is often called Calling a Function or Invoking a Function.

greet(); // Function Call or Invocation

// Output: Hello World!

Providing Input to a Function:

Often (More than Often really) there will be situations when we need to provide the function with some additional data, this is where the Parenthesis () comes into play. Within the parenthesis, we can provide a list of parameters or variable names: function exp(para1, para2){}

Providing the parameter list means we can now pass some data to the function while calling it, like so: exp(12, 34);. These parameters are nothing but variables that are accessible within the function & they provide access to the data passed to the function call. Data can be Literal Values or existing variables.

It will get more clear with this example:

function greet(name) {
    console.log("Hello, " + name);
}

// Passing Literal Value
greet("Shivangam Soni");
// Output: Hello, Shivangam Soni

// Passing Variable
const myName = "Test User";
greet(myName);
// Output: Hello, Test User

// Passing no Value
greet()
// Output: Hello, undefined

In this example, name is providing access to the string that was passed during the function call.

Another thing to note is that we can call a function without passing any data, in which case the parameters are defaulted to undefined, just like variables.

Getting Output from a Function:

This is all good, but what if I wanted my function to perform some action & give back the resulting data?

Well, Functions allow us to provide an output using the return statement, this output can be stored or directly used by the function's caller.

See this example:

function subtract(a, b) {
    return a - b;
}

// Directly using the Returned Value
console.log(subtract(12, 4));
// Output: 8

// Storing the Returned Value
const difference = subtract(23, 78);
console.log();
// Output: -55

An important thing to keep in mind, return is a terminating statement, which means the function stops executing after the return statement. So, any code written within the function, but after the return statement, will not get executed.

Return Multiple Values:

Functions can only return one value, i.e., if we write multiple return statements only the first one works. But you can simulate the effect of returning multiple values by returning an Array or Object & destructuring the result, For Example:

function divide(a, b) {
    const remainder = a % b;
    const quotient = Math.floor(a / b);
    return { remainder, quotient };
}

const result = divide(10, 7);
console.log(result.remainder, result.quotient);
// 3 1

// Inline Destructuring
const { remainder, quotient } = divide(25, 5);
console.log(remainder, quotient);
// 0 5

What are Functions Expressions?

Functions in JavaScript are First-Class Members, which means they can be stored in variables & such a function is called a Function Expression.

In Function Expressions, we can omit the Function Name, which makes it an Anonymous Function. But if provided, the name is only accessible within the Function, helpful for Recursion. Outside the Function, it's known by the Variable Name.

Example:

const getCircleArea = function(radius) {
    return Math.PI * radius ** 2;
}

getCircleArea(23);
// Output: 1661.9025

const  getRectArea = function rectArea(l, w) {
    return l * w;
}

getRectArea(10, 23);
// Output: 230

// Can't be called directly using Function Name
rectArea();
// ReferenceError: rectArea is not defined

Why use Function Expression?

Well, the main advantage of function expression is safety against Hoisting. Here's a Refresher on Hoisting, if needed.

A Normal Function gets Hoisted which means regardless of where you define a Function. It can be called at any point in the Script.

Using a Function Expression, you can make sure that the Function can only be called after it has been initialized.

Example:

normalFunc();
// Output: Normal Function
funcExp();
// Reference Error: can't access lexical declaration 'funcExp' before initialization

function normalFunc() {
    console.log("Normal Function");
}

const funcExp = function() {
    console.log("Function Expression");
}

What is an IIFE (Immediately Invoking Function Expression)?

An IIFE, as the name suggests, is a Function Expression that Invokes as soon as it gets declared. More clearly, it's an Anonymous Function Expression wrapped around a pair of parentheses followed by another pair of parentheses (the second pair for Invocation).

There are Several Uses for an IIFE:

  • Avoid polluting the Global Namespace.

  • Initiation Code that needs to be executed only Once.

  • Hiding Variables from being accessed publicly.

  • And more, Check here.

Because the Code within the IIFE is immediately executed, the script will run exactly like a normal JavaScript Program. Except for the fact that all the variables are bound to the Function Expression & not the Global Namespace.

This is useful in situations where hiding variables is important like, in a Game, You don't want the User to simply get a higher Score by updating the variable. The following code will prevent the access to gameScore variable through the Browser Console.

(function () {
    let gameScore = 200; // Not accessible Globally
    // Other Game Play Logic
})();

Some Real World Examples of Functions in JavaScript:

Event Handlers:

For a single event handler, it's better to use an Anonymous Function. But for situations where multiple events can perform the same action, we should declare the function to be reused.

// Anonymous Function
btn.addEventListener("click", function(event) {
    // Handle Event
});

// An Handler for Click of Add button as well as Press of "+" key
function handleAddition(e) {
    if(e.type === "click" || (e.type === "keydown" && e.key === "+")) {
        // Handle Event
    }
}

addBtn.addEventListener("click", handleAddition);
document.addEventListener("keydown", handleAddition);

Formatting Data:

The function below is used for padding additional 0s in front of a Number.

function padZeros(num, totalLen) {
    let numStr = num.toString();
    const numZeros = totalLen - numStr.length;
    for (let i = 1; i <= numZeros; i++) {
        numStr = `0${numStr}`;
    }    
    return numStr;
}

padZeroes(78, 4); 
// Output: 0042

Creating Objects:

An Object creating Function is called a Factory Function. This Function's purpose is to create objects of a predefined structure, without the need for defining a Class or Constructor Function.

function createPlayer(name, hp) {
    return {
        name: name,
        hp: hp,
        // ...Other Properties
    }
}

const player_one = createPlayer("Shiavngam Soni", 100);
const emeny_player = createPlayer("Nosalis", 250);