DEV Community

Cover image for Understanding callback functions and closures in JavaScript.
Swastik Yadav
Swastik Yadav

Posted on • Updated on

Understanding callback functions and closures in JavaScript.

Hello Everyone,

In this post we will explore the HOF (Higher order function), Callbacks, and the crazy JavaScript Closures which made us all pull our hairs at some point in our learning journey.

Higher Order Function

A function which accepts a function definition as a parameter and/or returns a function is HOF (Higher Order Function).

For instance:

function isEven(n) {
  return n % 2 === 0;
}

function printMsg(evenFunc, num) {
  const isEven = evenFunc(num);
  console.log(`The number ${num} is even: ${isEven}`);
}

printMsg(isEven, 2);
Enter fullscreen mode Exit fullscreen mode

In the above snippet printMsg is the Higher Order Function, because it accepts the isEven function as parameter.

Callbacks

A callback is a function passed into another function as an argument to be executed later. In the last code snippet isEven is the callback function.

It is called callback because it calls back to the place where it was created.

Let's see one more example.

let numbers = [1, 2, 4, 7, 3, 5, 6];

function isOddNumber(number) {
  return number % 2 !== 0;
}

function oddNumbers = numbers.filter(isOddNumber);
console.log(oddNumbers); // [1, 7, 3, 5]
Enter fullscreen mode Exit fullscreen mode

In the above code snippet isOddNumber is the callback function. Because isOddNumber is passed as argument to the filter function.

Callback functions can be used to handle Async JavaScript.

Closures

From execution context, we know that after a function is returned, it is removed from the call stack and deleted from execution context. So, keeping that in mind, here is the definition of a closure.

A closure is a function which has access to the outer variables even after the outer function is returned.

Once, the outer function is returned, it is removed from the callstack and deleted from execution context. But the inner function can still access the outer function variables. And this concept is known as closures.

let x = 10;

function foo() {
  let y = 20;

  function bar() {
    let z = 15;
    return x + y + z;
  }

  return bar;
}

let test = foo();
test(); // 45
Enter fullscreen mode Exit fullscreen mode

In the above code, bar is the closure function, which has access to outer variables (x and y) even after outer function is returned.

Simplified Closure Definitions:

  • A closure is function which remembers the environment in which it was created.
  • When a function is returned from an outer function, it carries the environment with itself.

Closures are possible in JS because of Lexical Scoping. Lexical scoping means, If a variable is not found in the local scope, it looks in the outer scope, and so on till the global scope.

lexical-scoping

Exception in closures

There is just one exeption in closures. In JavaScript every function is a closure except for functions created via "new Function" syntax.

Usually a function have access to the lexical environment where it was created. But when a function is created via the "new Function" syntax, it doesn't have access to the lexical environment but the global one.

function getFunc() {
  let value = "test";

  let func = new Function('value', 'alert(value)');

  return func;
}

getFunc()(); // Undefined
Enter fullscreen mode Exit fullscreen mode

So, functions such as func (in above code) doesn’t have access to outer variables, only to the global ones.


So, that's it for this post. I hope you learned something new, if so, please do share and join my Newsletter to receive epic weekly content on building your skillset.

Thank You!

Top comments (9)

Collapse
 
colocodes profile image
Damian Demasi

Nice article! I found a couple of mistakes, though.

Regarding HOF:
In the first code snippet, the printMsg function is missing an argument. It could be called like so:

//...
printMsg(isEven, 2);
Enter fullscreen mode Exit fullscreen mode

Regarding callbacks:
The code is not correct. It should be:

let numbers = [1, 2, 4, 7, 3, 5, 6];

function isOddNumber(number) {
  return number % 2 !== 0;
}

const oddNumbers = numbers.filter(isOddNumber);
console.log(oddNumbers); // [1, 7, 3, 5]
Enter fullscreen mode Exit fullscreen mode

Regarding closures and exceptions:
The definition is on point, awesome! But with the exception, the code has a mistake: the new Function statement is missing an argument:

//...
let func = new Function('value', 'alert(value)');
//...
Enter fullscreen mode Exit fullscreen mode

In this way, the actual result is undefined.

Collapse
 
swastikyadav profile image
Swastik Yadav

I really appreciate this, Damian. Thank you very much for correcting my mistakes and taking the time to write this. 😊

I have corrected the code snippets.

Collapse
 
nikpil93 profile image
Nikos • Edited

A very good explanation of these concepts is given also by Codesmith's channel.

youtube.com/c/Codesmith-School
youtube.com/watch?v=ZVXrJ4dnUxM
youtube.com/watch?v=_Sc3FXzIXg4

Collapse
 
adaminbiriistee profile image
ordinary guy

Perfect.

Collapse
 
swastikyadav profile image
Swastik Yadav

Thanks ordinary guy, It means a lot 😊

Collapse
 
jimajs profile image
Jima Victor

Well explained!👏

Collapse
 
swastikyadav profile image
Swastik Yadav

Thanks a lot 😊

Collapse
 
imiahazel profile image
Imia Hazel

Thanks. You are master in explanation and delivering the concepts. :)

Collapse
 
swastikyadav profile image
Swastik Yadav

Thanks Imia, You are so kind.

You made my day. 😊