Skip to main content

Closures

· 5 min read
Hassan Ali
Front End Engineer

Closure

  • Functions can define functions, return the inner function and it will "remember" scope. mdn
  • e.g. In Higher order function we can pass function as arguments then they also return the function. But in closure we can declare another funtion within the function. The inner Function has own scope and they have access of the scope of the parent function where they define.
info

Keep in mind when we talked about higher order functions, we said that functions can return other functions as outputs just like theycan take in other functions as inputs like map and filter and reduced it.

Now here's the other thing, within the body of a function you can define another function.And because the body of a function has its own scope,its own notion of the values of variables. When you define an inner function,that inner function has access to the outer function scope.It has access to whatever values that outer function is working with.

So if you define a function within another function,when you return out that inner function, an interesting thing happens.Which is that you have the possibility for that inner function onceit's returned to remember values from the scope in which itwas defined even if those are not being passed in directly to the function.

Example

function makeAdjectifier(adjective) {
return function (noun) {
return adjective + " " + noun;
};
}

const coolify = makeAdjectifier("cool");
coolify("workshop"); // "cool workshop"
coolify("drink"); // "cool drink"

Partially Apply Functions

A function which takes multiple arguments, and kind of lock in some of the values.And so partial application is this notion of kind of remembering certain arguments and being able to then reuse functions more easily because, I don't have to keep passing in the same value over and over again. a related concept in functional programming called currying.

Currying

Currying is the process of taking a multi-argument function, a function that takes in multiple values as its input arguments and breaking it up in a sense, into a series of single argument functions,which successively, remember the outer scope, sothat I can partially apply each of those multiple argumentsto create again more reusable functions that I can use tocreate more complex programs out of simple functions.

Example

function greet(greeting, name) {
return `${greeting}, ${name}!`;
}

function curryGreet(greeting) {
return function (name) {
return `${greeting}, ${name}!`;
};
}

const greetItal = curryGreet("Ciao");
greetItal("Alonzo"); // "Ciao, Alonzo!"

const greetTex = curryGreet("Howdy");
greetTex("Alonzo"); // "Howdy, Alonzo!"
greetTex("Alan"); // "Howdy, Alan!"

Let's take a look at some code because me yapping is not gonna help this setting very well.All right.

Here I've got my old greet function, if you remember from earlier,which takes in a greeting and a name, and returns out, hi Alan or Howdy, Alonzo.

function greet(greeting, name) {
return `${greeting}, ${name}!`;
}

Now what I'm doing is I'm making a curried version of that greet function,which I'll call curly curry.Greet which is a single argument function, it takes in a greeting,then it returns another single argument function, which takes in a name,and returns the same result as our original greet function did.

function curryGreet(greeting) {
return function (name) {
return `${greeting}, ${name}!`;
};
}

So now, if I wanna greet lots of people with the same greeting, I don't have to keep passing in that greeting over and over and over again,I can create a new function like greet Italion sort of function, that I am going to create by calling curryGreet on the greeting that I want to use like Ciao.

const greetTex = curryGreet("Howdy");
greetTex("Alonzo"); // "Howdy, Alonzo!"
greetTex("Alan"); // "Howdy, Alan!"

And because of closure, this inner function remembers that Ciao that greeting, and is going to be able to output the desired string even though I didn't have to keep passing Ciao in.

note
  • Closure being, the concept through which,that inner function can remember, the outer function scope.
  • Currying, being the process of taking that multi-arg function,and breaking it down Into a series of single argument functions, which thanks to closure, allow me to partially apply that multi argument function and create a version that remembers the first argument I passed in and gives me a new function I can call on the second argument.

Why are we doing it like this instead of just using our original function and passing in the two arguments, the greeting and then the name each time that we wanna greet a new person? (why do we have such a simple function when we could just write the string?)

That's a good question.And in this case, this is a really, really simple example that's just for demonstration purposes, just to try to drive the idea through.

  • A lot of cases where being able to split up arguments like this, and being able to lock in some of those arguments so that we have a function that we can reuse again and again.
  • Will be, useful because the computation is more complex than just smashing some strings together.So in this case, the functions here on these slides are really simple just to try to convey the point.And this is probably not the type of code that any of us need to write very often.
  • why you'd wanna break down operations into really simple chunks, so that you can use them over and over again without having to repeat yourself a lot.

Exercise

Reference