This article is recommended for beginners who often find themselves confused when trying to understand how functions work in JavaScript. As you may already know, functions are one of the most essential and core features of JavaScript, with several ways to represent them. Here below I will be discussing about different types of functions, how they work, and their key features.
What is a function ?
- In JavaScript, functions are reusable blocks of code designed to perform a specific task. They allow you to group together a set of instructions that can be executed whenever needed by calling the function.
- Functions can take inputs, called parameters, process them, and return an output. They help in making code modular, readable, and reusable, which is essential for efficient programming.
- You can create a function at any moment, pass it as a parameter to another function, and execute it again in a completely different part of your program (a feature known as callable).
- If a variable is defined within a code block , that variable will only be accessible within that code block. (see scope)
Types of Functions in JavaScript
JavaScript has different types of functions, each with its own use case. Let’s look at the most common types:
1. Simple Functions declarations/ Function Statement
So as all of we know this is a simple ways of function declaration also called a function statement. This is the traditional way to define a function →
function printHello(name){ // It took one parameter named "name".
console.log(“ Hello ” + name);
}
printHello(“Irem”); // We called and executed the function by passing an argument.
Output: Hello Irem
Parameter: The values we define inside the parentheses () when declaring a function.
Argument: The values passed to the function when it is called.
Inside the function, arguments and parameters behave like local variables.
function add(a, b) {
return a + b;
}
console.log(add(5, 3)); // Output: 8
// Here, the add function takes two arguments, adds them,
// and returns the result. You can call add() multiple times with
// different values without rewriting the logic every time.
In a Declaration Function:
- You can call (execute) the function even before the line where it is defined. This is because it is hoisted.
- It does not execute immediately upon being written; it is not self-invoking. Instead, it is saved for later use and performs its task only when it is called (invoked).
- You must give the function a name.
FUNCTION SCOPE
// The code here cannot use firstName, but it can use lastName.
let lastName = "smith"; // global variable
function myFunction() {
let firstName = "john"; // local variable
// The code here use both firstName, lastName.
}
// The code here cannot use firstName, but it can use lastName.
FUNCTION INVOCATION (Calling/Executing)
- When invoked by JavaScript code,
- When an event occurs (for example, when a user clicks a button),
- Automatically (self-invoked).
2. Function Expression
A function defined as part of an expression and typically assigned to a variable. It can be named or anonymous. Function expressions are not hoisted, meaning you cannot use them before they are defined.
// FUNCTION EXPRESSION ASSIGNED TO A VARIABLE
const greet = function(name){console.log(`Hello, ${name}!`)}
greet('Alice') output: Hello, Alice!
3. Arrow Function
Arrow functions provide a shorter syntax and are introduced in ES6.
const multiply = (a, b) => a * b;
console.log(multiply(4, 2)); // Output: 8
4. Anonymous Function
A function without a name, often used in function expressions, callbacks, or IIFEs. Since it lacks a name, it cannot be directly referenced elsewhere. Since they are called using variable names, you can use multiple anonymous functions in the same array.
Moreover, since they are assigned to a variable, you can use that variable as a parameter in another function to create a callback.
5. Callback Function
A function passed as an argument to another function to be executed later. It allows asynchronous or event-driven programming.
6. Higher-Order Function
A function that either takes another function as an argument, returns a function, or both. It’s a powerful tool in functional programming.
Now that we've covered these definitions, let's see how they come together in simple example.
function doubleResult(num1, num2, callb) {
return calc(num1, num2) * 2;
}
function add(num1, num2) {
return num1 + num2;
}
function multiply(num1, num2) {
return num1 * num2;
}
console.log(doubleResult(4, 2, add));
(output) => 12;
console.log(doubleResult(4, 2, multiply));
(output) => 16;
1- The doubleResult function accepts 3 arguments: 'num1', 'num2', and 'callb'.
2- callb is passed as the 3rd argument, processes the given arguments, and returns the result.
3- Inside the doubleResult function, the add and multiply functions are used as callbacks.
add() adds the arguments, while multiply() multiplies the arguments.
4- When the doubleResult function is called in the log, 'num1' and 'num2' are passed as arguments,
while the add or multiply functions are passed as the 3rd argument (callback).
doubleResult() => Higher-order function
add() and multiply() => Callback functions
We could assign a function to a variable, right (expression)? This means we can treat this function the same way we treat variables. In other words, that variable becomes a 'First-Class' entity for us.
7. First-Class Function
In JavaScript, functions are first-class citizens, which means they can be treated like any other variable. You can assign a function to a variable, pass it around as an argument, or even return it from another function. This is a powerful feature that enables functional programming patterns.
const sayGoodbye = function () {
console.log("Goodbye!");
};
const greetAndSayGoodbye = function (callback) {
console.log("Hello!");
callback();
};
greetAndSayGoodbye(sayGoodbye);
// Here, sayGoodbye is passed as a callback to the greetAndSayGoodbye function,
// showing how functions can be assigned to variables and passed around.
8. Immediately Invoked Function Expressions (IIFE)
An IIFE is a function that is defined and immediately invoked (called) after its creation. It is often used to create a new scope, keeping variables inside the function private.
let result = (function(x, y) {
return x + y;
})(3, 5);
console.log(result); // output: 8
----
(function() {
console.log(5 + 12) // output: 17
})()
In this example, instead of assigning the function to a variable in the usual way, we directly place the function inside parentheses (so it gets called as it is created), then pass the parameters inside the parentheses and call it, assigning the returned result to the result variable.
IIFE wraps the code inside it within its own scope. This ensures that variables and functions defined inside it do not interfere with the outside code, while variables defined outside can still be accessed from within the IIFE. This helps prevent variable name collisions and creates safer code. By wrapping the code in its own scope, IIFE does not interfere with the outside code.
9. Recursive
function flattenArray(arr) {
return arr.reduce((flat, toFlatten) => {
return flat.concat(
Array.isArray(toFlatten) ? flattenArray(toFlatten) : toFlatten
);
}, []);
}
// Example usage
const nestedArray = [1, [2, 3], [4, [5, 6]]];
console.log(flattenArray(nestedArray));
The flattenArray function takes a nested array and converts it into a flat array by recursively traversing its elements. The first parameter is a 'combining function' (flat, toFlatten). The second parameter is the initial value (here, an empty array [])
How it works:
- It uses the reduce method to iterate over the array.
- For each element:
- If it's an array, the function calls itself (flattenArray) to flatten that sub-array.
- If it's not an array, it simply adds the element to the flattened result using concat.
I hope this article is helpful to you down the road!