Skip to main content

Closure

Functions & Callback

Higher Order Function ⇒ Fill functionality in a function with a parameter. Functions are like objects and can be passed. And they will be run later.

  • They take in a function or produce a function in return.

In JS functions are first class objects = they have everything an object has. They can be treated as objects.

The outer function is the higher order function. The inner one is called the callback function.

Closure

  • Enables pro-level functions like ‘once’ and ‘memoize’
  • Many design patterns use closure

Everytime a function executes, a brand new memory (execution context) is created. Functions dont remember the previous memory. But if we could, that would change everything.

  • Functions with memories

We create a Local memory / variable env. / state for function’s execution context

When function finishes executing, this gets deleted

What if we could hold on to live data between executions?

It starts with returning a function from another function.

Next time we run this function, it could remember data from previous runs.

Why would be do this? Getting a function to global memory, from the execution context’s memory where it was created..

Screenshot 2023-08-11 at 20.29.51.jpg

Screenshot 2023-08-11 at 20.29.45.jpg

One would assume that, in the code above the reference to counter would be lost after the function outer is executed and its execution context is deleted. That is in part correct. But when we return a function from a function, the surrounding data is returned back to global memory along with it!

This allows functions to have their own data, stored in the global memory with them.

// should return singleton object
const a = () => {
const obj = { a: 1 };
const getObj = () => {
return obj;
};
return getObj;
};

// Should return new object every time
const b = () => {
const obj = { a: 1 };
return obj;
};

const getSingleton = a();

console.log("should be true", getSingleton() === getSingleton());
console.log("should be false", b() === b());

when the function returned from a function is stored in global memory, it gets a hidden property [[scope]]. It points where all these other values in the memory from its execution context is stored. we can’t access it in any other way than running the function. therefore, this can be called ‘private’ data in sense that nothing other than the function can access it.

use case: you can have a function only run once, by checking the counter in its scope.

In these ‘backpacks’, the data in the scope of the execution context that is carried to global memory, only the data we reference in the function are passed. (in the never JS engines, optimized) so that we don’t have memory leaks.

Closure Technical Definition & Review

scope = what data and rules are available for the code at the current line

Js’s scope rule = LEXICAL SCOPING (STATIC SCOPING)

Where I save my function, sets what data that function has access to for the rest of its life.

The function carries the scope it was created it in, along with it to whatever memory it moves to.

Bring the data with us from where the function was born.

Backpack (or it’s called closure of the function generally) is a result of JS being a lexically scoped language.

Screenshot 2023-08-12 at 03.29.40.jpg

Applications of Closure

Untitled

memoization ⇒ giving functions persistence memories of previous input - output combinations. For example a prime number finder function (calculation heavy function) can keep a record of previous calculations for an input, and return it if that exists.

iterators ⇒ returns the next element in a list, by keeping the last element in scope.

module pattern ⇒ where can we keep data we want to exist throughout the whole application lifespan. we can’t put it in functions as they’ll be deleted. You can put it in global, but it’ll pollute the global scope. module pattern achieves this without polluting global label namespace.

you can use function backpacks to store and persist data.