Types of Functions in Java Script

A Beginner's Guide

Types of Functions in Java Script

Introduction

JavaScript, the versatile language that powers much of the web, is celebrated for its ability to create dynamic and interactive web applications. At the heart of JavaScript's magic lies a fundamental building block: functions. Understanding the various types of functions in JavaScript is like holding the keys to unlock the true potential of this language.

If you're new to JavaScript, you're in the right place. Functions are not just a mere concept; they are the backbone of JavaScript programming. In this beginner's guide, we'll take you on a journey through the different types of functions in JavaScript, from the basic function declarations to the modern arrow functions and much more.

By the end of this guide, you'll have a solid understanding of how to declare, use, and harness the power of functions in JavaScript. Get ready to unlock new possibilities and elevate your coding skills! 🚀📜

Function Basics

Let’s start with what we already know. Functions are a reusable piece of code that performs a specific task and produces some kind of output.

They are designed to be used multiple times, making your code more organized and efficient. Just like we have functions in our mathematics like in the below picture

Similarly, we also have a specific syntax in Java script which we will see in the next section.

Functions play a crucial role in breaking down complex tasks into smaller, manageable pieces. They promote code reusability, making your programs more efficient and easier to maintain. As you delve deeper into JavaScript, you'll discover various types of functions that cater to different programming needs.

Function Declaration

As I said there is a specific syntax that we have to follow in Java script to declare a function. Let’s put all of that in one picture.

As we know, keywords are words that have predefined meanings in that programming language. Here, the function keyword is used to declare a function. After the keyword, we have to provide a name for our function. We are going to use this name for that piece of code wherever we want.

The code in the function body might require some information to execute, we provide such information through the parameter within the curly braces. We can pass multiple parameters by separating them with a comma.

The reusable logic of the code will be present in the function body. The function body should be surrounded by curly braces {} . Everything that we define within the curly braces will be local to that function, if we create a variable inside the function body we cannot access it outside the function body.

In most scenarios, you might need some kind of result out of the function which we can use further in our code. In such scenarios, we can use the return keyword. It outputs the data which we can store in some other variable.

Let’s see a quick example

function calculateExpression(x) {
  console.log("The x value is:", x);
  return 2 * x + 3;
}

let value = calculateExpression(9);
console.log("The result value is:", value);

Here, we are invoking the calculateExpression function by providing 9 as an argument to the x parameter. The output of the function is stored in value a variable. Now, we can use that information for some other calculations, here we are just printing it onto the screen.

I am using Node Js to run my JavaScript, you can use any online interpreters of your choice.

Here is the output when I run the above code:

That’s how we declare and call the functions in JavaScript.

Function Expressions

Function expression is a concept that is available in Java Script which allows us to store functions in a variable. The difference between function declaration and function expression is we don’t need to write the name of the function in the function expressions.

Check out its syntax:

Clearly, it is an expression, just like any expression it also has a LHS and RHS. The LHS part of the expression is our variable name and the RHS part of the expression is a function. As we can see the function name is missing from the above syntax. Instead, we have a variable where our function definition is stored. Now, we can use the variable name for calling the function. Just like how we did earlier

const calculateExpression = function (x) {
  console.log("The x value is:", x);
  return 2 * x + 3;
};

let value = calculateExpression(9);
console.log("The result value is:", value);

This produces the same results as we have seen earlier. However, I'd like to emphasize the use of the const keyword for the calculateExpression variable. We deliberately chose const because it ensures that the variable can't be reassigned after initialization. This decision helps prevent potential issues like the one we encountered when using let or var as shown below.

let calculateExpression = function (x) {
  console.log("The x value is:", x);
  return 2 * x + 3;
};

// Some other code here

// Accidentally overwritten the calculateExpression variable
calculateExpression = 5;

// Some other code here

let value = calculateExpression(9);
console.log("The result value is:", value);

In bigger projects, we might accidentally overwrite the variable and we will not be aware of that. In such cases, we will get an error like this.

So, when we use the const keyword we will get a different message like this which is a bit easy to debug.

As we have seen, we are able to achieve the same thing with both the function declaration and function expression.

But, In Java script function declarations are hoisted, which means we can call the functions even before defining them. Function expressions are not hoisted, which means we can’t call the function before defining them.

Clearly, we are not able to access it before initialization in the case of function expressions.

Anonymous Functions

As the name suggests anonymous functions are anonymous. That is they will not have a name. We have already seen an anonymous function in the previous section.

Any functions that do not have a name are simply called anonymous functions. Just like function expressions, anonymous functions have many other use cases in JavaScript. They can be assigned to variables and passed to other functions as arguments, like event handlers, callback functions, and higher-order functions (we will explore more about these in this blog), etc.

Callback Functions

Imagine you have a function that takes a long time to execute and, in this process, it blocks the rest of your code from running. In such situations, we can make that function asynchronous, which means it runs in the background, allowing the rest of your code to continue smoothly without waiting. Now, the challenge is how do we know when this background task is completed? That's where callback functions come to the rescue.

You can provide another function as an argument to this asynchronous function, and this function will be executed once the time-consuming task is finished. It's like saying, "Hey, do this work in the background, and once you're done, let me know so I can handle the results."

The best example that I can provide for this is setTimeout function in JavaScript. It is an asynchronous function that will take another function as an argument and time in milliseconds. When we run this function it will wait in the background for the provided amount of time and call the function after that. Here’s the code

function greet() {
  console.log("Hello People! 🙋‍♂️");
}

setTimeout(greet, 2000);

console.log("I will print first..");

Here, we have a simple greet function that will print some text to the console. We asked the setTimeout to call the greet function after 2000 milliseconds i.e. 2 seconds. The greet function is passed as an argument to the setTimeout which will be called after some time. Hence, we call the greet function a callback function.

As setTimeout is an asynchronous function it will go to the background and “I will print first..” will print on the screen first, then the "Hello People! 🙋‍♂️" text after 2 seconds. Here’s the output:

We can also use anonymous functions as shown below which will produce the same result.

setTimeout(function () {
  console.log("Hello People! 🙋‍♂️");
}, 2000);

console.log("I will print first..");

Arrow Functions

Arrow functions are just a new way of writing functions in Java Scripts which were introduced in ECMA Script 6. Arrow functions have shorter syntax than a normal function expression. In essence, arrow functions can achieve the same functionality as function expressions, but with less typing involved.

Let’s see how arrow function syntax makes life simpler.

We can use this syntax as shown below

const calculateExpression = (x) => 2 * x + 3;

let value = calculateExpression(7);
console.log("The result value is:", value);

You can also use this syntax for callbacks also

setTimeout(() => {
  console.log("Hello People! 🙋‍♂️");
}, 2000);

console.log("I will print first..");

Though arrow function syntax is simpler to write, they have their own limitation compared to actual function declarations which you can study more here.

IIFE

It stands for Immediately Invoked function expression. As the name suggests these functions are called immediately as soon as they are defined. These are also known as self-executing anonymous functions which makes more sense. We already know what anonymous functions are ( just function definitions without a name). So, when these anonymous functions are executed immediately, we call them IIFE.

Here’s the syntax:

You can also do the same with the arrow function syntax.

(function (x) {
  console.log("The x value is:", x);
  return 2 * x + 3;
})(8);

You might be wondering if we are calling those functions immediately then what’s the point of defining the function? We can directly write those function logic without defining it. Yeah, you are right and there are a few special use cases for this syntax like

  • Avoid polluting the global namespace

  • Execute an async function etc.

You can explore more about them here.

Higher Order Functions

This is just a new name given to the functions that we already know. Do you remember the setTimeout function that we have used in the callback functions section? Yeah, it is a higher order function. Like that, there are many other inbuilt higher order functions that we are using daily. The actual definition goes like this:

The functions which can take other functions as arguments or they can also return other functions as their output are called Higher order functions.

One more best example that I can give is the map method of Array objects. Let’s say you have an array like below

const numbers = [1, 2, 3, 4, 5];

Now you can create a new array out of these numbers where each number in the new array is double of existing number. For that, we have a function that can double a given number like below

const double = function (x) {
  return 2 * x;
};

This function will take a number and return a doubled value of that number. Now, we have to call this function for each value in the numbers array and store the result in a new array.

This is where the map method function comes into play. Check this out

const doubledNumbers = numbers.map(double);
console.log(doubledNumbers);

Here’s the output:

The map method of the numbers array is calling the double function on each value and stores the result of the function in a new array which is exactly what we needed.

The key point here is we are passing another function as an argument to some other function. Hence, the map method of an array is a higher order function. There are many other higher order functions that are available in Java Script and you can also create your own.

Note: We can also write the same logic with a few lines of code using anonymous function and arrow function syntax like below

const numbers = [1, 2, 3, 4, 5];

const doubledNumbers = numbers.map((x) => 2 * x);
console.log(doubledNumbers);

It will also produce the same result.

Generator Functions

Generator functions are a special type of function with some special power. Let’s say you want to generate a range of numbers like a range of prime numbers between 1 to 100. The way in which you can achieve this is to generate all the numbers, store them in an array, and return the array. The other way is to find a prime number then return it and if required generate the next prime number and return that and so on.

That means instead of generating all the values at once we will generate one value at a time, pause the function, and generate the next value only when required. If you understand that you might have realized how efficient that can be.

Let’s see how we can do this. There is a special syntax that we have to follow when defining generator functions

The first change is to put a start after the function keyword which makes it a generator function and we have to use yield keyword instead of return. Because as we know return will completely stop the execution of the function but, yield will produce the output and temporarily pause the execution of the function until we ask for the next value.

Let’s write this code and see what we will get

function* generateNumbers(n) {
  for (let i = 1; i <= n; i++) {
    yield i;
  }
}

numbers = generateNumbers(3);
console.log(numbers)

Output when I run the above code:

Generally, what we expect is an array of numbers from 1 to 3 but, It says the numbers variable is a generator object. If I run the same code in the browser console we can see more details about this object

This generator object will not run the function body when you call it like this generateNumbers(3). It will just produce a generator object. Now, the question is how can we execute the function body?

We can do it by calling a method of this object that is next() method. Now run the below code and see the output

console.log(numbers.next());

The output:

We got an object with two fields i.e a value field and a done field. The value field is the value that you got from the yield keyword and done field is whether all values are generated or not, here it is false which means there are still values that can be generated from this function.

Here is how the next() method works. The code inside the function body will run when we call the next() method. It will run only until it encounters the yield keyword. When it sees the yield keyword it returns the value that we have seen in the output and it will pause the execution of the function body until we call the next() method again. Now, Let’s call the next() method multiple times and see how the output. This is how your code should look like

function* generateNumbers(n) {
  for (let i = 1; i <= n; i++) {
    yield i;
  }
}

numbers = generateNumbers(3);

console.log(numbers.next());
console.log(numbers.next());
console.log(numbers.next());
console.log(numbers.next());
console.log(numbers.next());

The Output:

Now I called the next() method of the generator object five times. Every time I call it, it will execute until it sees the yield keyword and it will pause the execution. As we can see the first three times we got the values from 1 to 3 and the done keyword is false which specifies whether all values are generated or not.

The fourth time and the fifth time when I called the next() method on numbers the value is undefined and the done is true which means all the values have been generated from the function. That’s how the generator functions work.

We can also use these generator functions directly in the for...of loop like below.

function* generateNumbers(n) {
  for (let i = 1; i <= n; i++) {
    yield i;
  }
}

numbers = generateNumbers(3);

for (let num of numbers) {
  console.log(num);
}

The output:

Here, the for…of loop will take care of calling the next() method until the done property is true.

We can use these generator functions when you want to produce values lazily and pause their execution or in cases where you want to generate values on demand like streaming large amounts of data in chunks over the network etc.

Conclusion

  • Functions are the backbone of JavaScript, enabling dynamic web applications and efficient code.

  • Understanding different function types empowers you to choose the right tool for the job.

  • We covered the basics, function declarations, expressions, and the power of callback functions.

  • Arrow functions offer a modern and concise way to write functions.

  • Immediately Invoked Function Expressions (IIFE) help isolate code blocks.

  • Higher-order functions like map for simplifying data manipulation.

  • Stay curious as you explore even more fascinating concepts like generator functions.

  • Embrace the versatility of JavaScript functions in your coding journey. Happy coding! 🚀📜

Thanks for Reading

If you came this far, I appreciate your commitment to learning JavaScript. I hope this guide has equipped you with valuable insights into the various types of functions in JavaScript.

If you have questions, feedback, or topics you'd like us to cover in future blog posts, please feel free to reach out. Until then Stay curious, keep coding, and see you in the next blog post! 🚀📚

Bye People! 🙋‍♂️