Functional JavaScript — Closures. Inner functions are useful.
By: John Au-Yeung
Tags: Programming, JavaScript, Software Development, Web Development, Technology

Photo by Frame Harirak on Unsplash

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to use closures.

Closures

Closures are inner functions.

An inner function is a function within a function.

For example, it’s something like:

function outer() {

function inner() {}

}

Closures have access to 3 scopes.

They include variables that are declared in its own declaration.

Also, they have access to global variables.

And they have access to an outer function’s variable.

For example, if we have:

function outer() {

function inner() {

let x = 1;

console.log(x);

}

inner();

}

then the console log logs 1 because we have x inside the inner function and we access it in the same function in the console log.

The inner function won’t be visible outside the outer function.

We can also access global variables within the inner function.

For example, if we have:

let global = "foo"; function outer() {

function inner() {

let a = 5;

console.log(global)

}

inner()

}

Then 'foo' is logged since inner has access to the global variable.

Another scope that inner has access to is the scope of the outer function.

For example, we can write:

function outer() {

let outer = "outer" function inner() {

let a = 5;

console.log(outer);

}

inner()

}

We have the outer variable and we access it in the inner function.

Closure Remembers its Context

A closure remembers its context.

So if we use it anywhere, the variables that are in the function are whatever they are within the original context.

For example, if we have:

const fn = (arg) => {

let outer = "outer"

let innerFn = () => {

console.log(outer)

console.log(arg)

}

return innerFn;

}

Then the outer and arg variable values will be the same regardless of where it’s called.

outer is 'outer' and arg is whatever we passed in.

Since we return innerFn with fn , we can call fn and assign the returned function to a variable and call it:

const foo = fn('foo');

foo()

We pass in 'foo' as the value of arg .

Therefore, we get:

outer

foo

from the console log.

We can see that the values are the same even if we called it outside the fn function.

Real-World Examples

We can create our own tap function to let us log values for debugging.

For example, we can write:

const tap = (value) =>

(fn) => {

typeof(fn) === 'function' && fn(value);

console.log(value);

} tap("foo")((it) => console.log('value:', it))

to create our tap function and call it.

We have a function that takes a value and then returns a function that takes a function fn and runs it along with the console log.

This way, we can pass in a value and a function.

Then we get:

value: foo

foo

logged.

The first is from the callback we passed in.

And the 2nd is from the function we returned with tap .

Photo by Jason Leung on Unsplash

Conclusion

Closures are inner functions.

They have access to the outer function’s scope, global variables, and their own scope.

We can use it or various applications.