JavaScript is a programming language that is used in both FrontEnd and BackEnd to build interactive web applications. It is the only scripted language that the browser can understand. As far today, almost 98% of websites use this language on the client-side for web page behavior. It is the most popular programming language in the world.
But the journey of this language was not so smooth. This language was designed by Brendan Eich
and first appeared on December 4, 1995. At the initial moment, it was only used to bring interactivity to the web pages while the HTML and CSS are used to structure and design the web page.
The Game-changing moment happens when Ryan Dahl
introduces NodeJS for the first time in 2010. It is nothing but an open-source, cross-platform, back-end JavaScript runtime environment that runs on the V8 engine and executes JavaScript code outside a web browser.
Since that moment this language has been used widely. In 2022, it is worth learning this amazing language to build a strong career in the Web Development sector. To make your learning journey smooth and also make your base solid, today, I will discuss the concepts of JavaScript those are Currying, Closure, and Callback (CCC).
No matter which position you are in now! If you want to make yourself a good JavaScript developer then you need to have a solid understanding of these topics. Moreover, it will help you to crack interview questions because most of the time there’s a common question that interviewers ask about these topics. At the end of this tutorial, you will get a clear understanding of Currying, Closure, and Callback in JavaScript.
Things You will learn from this tutorial
We will cover the following topics in this tutorial:
- Function as First-Class Citizen
- Currying
- Closure
- Callback
Function as First-Class Citizen
Before learning about the CCC’s concepts, you need to understand the concept of a First-Class Citizen. In JavaScript, a function is said to be a First-Class Citizen for the following three reasons
- A function can be assigned as a value to a variable
- A function can be passed as an argument to other functions
- A function can be returned by another function
Let’s take a look at some code snippets that show how a function in JavaScript can satisfy the above three reasons
A function can be assigned as a value to a variable
const myFunc = name => `Hello, ${name}! `;
const result = myFunc("Rahul");
console.log(result);
// Output: Hello, Rahul!
Here, you can see that we have declared an arrow function and later on, we have stored it into a variable named myFunc
.
A function can be passed as an argument to other functions
const myFunc = (greetings,name) => `${greetings()}, ${name}! `;
const hello = () => "Hello"
const bonjour = () => "Bonjour"
const salut = () => "Salut"
const result_1 = myFunc(hello,"Rahul");
const result_2 = myFunc(bonjour,"Rahul");
const result_3 = myFunc(salut,"Rahul");
console.log(result_1);
console.log(result_2);
console.log(result_3);
// Output:
// Hello, Rahul!
// Bonjour, Rahul!
// Salut, Rahul!
Instead of hard-coding “Hello” in our function myFunc
, we now accept a parameter which is a function. As you can see, there are three different functions hello
,bonjour
and salut
and each of them are passed as an argument to myFunc
A function can be returned by another function
const outerFunc = () => {
console.log("Outer Function")
const innerFunc = () =>{
console.log("Inner Function")
}
return innerFunc
}
outerFunc()()
// OUTPUT
// Outer Function
// Inner Function
const myFunc = outerFunc()
myFunc()
myFunc()
// OUTPUT
// Outer Function
// Inner Function
// Inner Function
We have a function named outerFunc
. It doesn’t do much, it simply prints a statement to the console. Another function called innerFunc
is created inside. The innerFunc
also doesn’t do much, it simply prints a statement to the console. The outerFunc
returns the innerFunc
.
There are a couple of ways this can be used. The first way is to use two braces together. The first pair of brackets invokes outerFunc
and the second pair of brackets invokes the object returned by outerFunc
, i.e the function innerFunc
.
In the second way, we store the returned function in a variable and invoke it it like a normal function
Currying
In simple terms, Currying is a technique of chaining multiple functions. It’s a functional programming feature. Let’s understand this concept by solving a common interview question :
The Question
Look at the below code snippet.
function sum(x, y, z){
return x + y + z
}
console.log(sum(10, 20, 30))
// Output: 60
The task you need to perform is to call the sum
function like sum(10)(20)(30)
instead of sum(10, 20, 30)
this.
// Current way of Invoking function
sum(10, 20, 30)
// Desired way of Invoking function
sum(10)(20)(30)
How can you perform this action? The answer is simple, the term you need to use is Currying. See the below code example:
function sum(x){
return function(y){
return function(z){
return x + y + z
}
}
}
console.log(sum(10)(20)(30))
// Output: 60
Here, you can see that we have declared a function inside another and these have created a function chaining. You can also see we are getting exactly the same output and this process is known as Currying in JavaScript.
Currying is used in popular javascript libraries such as Lodash and Rambda
Closure
A closure in JavaScript is nothing but a function that references variables in the outer scope from its inner scope. Let’s see the problem that closure solves in the below section and by doing so, you will be able to know why we need to learn the concept of closure in JavaScript.
function sayHello(){
let name = 'Rahul'
function inner(){
console.log(`Hello ${name}`)
}
return inner
}
let abc = sayHello()
console.log(abc)
// Output:
// [Function: inner]
// Hello Rahul
Here, you can see that we are getting the output as expected. But the main question is how we are getting this? Let’s break it down in the below section:
At first, we declared a function named sayHello()
and stored a string inside the name
variable. Later on, we declared another function and print the name with a Hello
message, and returned the inner()
function. Finally, we have stored the returned function into the abc
variable.
Now, when JavaScript will execute the code it will not find the name
variable as the sayHello()
function’s memory has been destroyed. But how we are getting the output as expected?
The main reason behind this is that Closure. Here, it is true that the sayHello()
function’s memory has been destroyed but it creates a reference of that function and as a result, while executing the inner()
it can access the variable from the reference of the sayHello()
function. To perform this action, you don’t need to write one line of extra code. Because the JavaScript engine is smart enough to perform this action. All you need to do is to understand the concept of closure and it is created by default every time when a function has been created in JavaScript.
Callback
A callback is a function passed as an argument to another function. Let’s look at a use case below.
Suppose, we have an array of names saved in our database. We want to add a new name and later on, we want to print the names with the newly added name. To perform this action we have written the below code:
let names = ['Rahul','Rohit','Rohan']
function addNewName(name){
setTimeout(function(){
names.push(name)
},5000)
}
function printNames(){
setTimeout(function(){
console.log(names)
},3000)
}
addNewName('Alex')
printNames()
// Output:
// [ 'Rahul', 'Rohit', 'Rohan' ]
Here, you can see that, we have added the functionality for adding new names but in the output, the new name has not been added. The main reason behind this is the asynchronous
behavior of JavaScript. We know that for tasks that take much time, JavaScript does not wait for them, rather they work on other lighter tasks and keep the heavy task in the queue. The same things happen here.
We need to use a callback function so that we can break the asynchronous
behavior of JavaScript and it can wait for us based on a specific task. See the below code example to understand it more clearly:
let names = ['Rahul','Rohit','Rohan']
function addNewName(name, cb){
setTimeout(function(){
names.push(name)
cb()
},5000)
}
function printNames(){
setTimeout(function(){
console.log(names)
},3000)
}
addNewName('Alex',printNames)
// Output:
// [ 'Rahul', 'Rohit', 'Rohan', 'Alex' ]
We have passed a function (printNames) as an argument to another function (addNewName). This time printNames
will execute only after the previous functions have been executed. This concept is known as the Callback and you can see that we have called this function after the previous function finished its tasks. That’s the reason we have mentioned Callback as Call later.
There are many advanced concepts that have been built on top of the Callback. You may also have heard about the concept of Callback hell
. I’ll be discussing this in one of the future articles.
Conclusion
In this tutorial, we have covered three essential concepts of JavaScript (Currying, Closure, and Callback). I hope you found this article helpful and informative.