Closures and Factory Functions

Function call, Private and Public variables, Closures, Factory Functions

·

5 min read

Closures and Factory Functions

Before starting Closures , let's first understand Function Call.

How Function Call works ?

Let's say we call a function sayHello(), now "sayHello" will be reference to the function and "()" will make function call.

image.png

Now let's look in the memory,

image.png

sayHello is only reference to a function, if we only print sayHello it will not print desired output, but if we write () along sayHello i.e. sayHello() then function will be called and we will get desired output.

Now what will be the output of the following code ?

function sayHello() {
    return "Hello I am a Function.";
}

const hello = sayHello;

here sayHello is reference to a function, if it is assigned to another variable hello, the hello variable will also point to same function as sayHello does.

image.png

If we do this,

console.log(hello);

// output will be: - 
// [Function: sayHello]

here it says that hello is reference variable to a function named sayHello().

Now, if we do this,

console.log(hello());

// output will be: - 
// Hello I am a Function

a function call will be made.

Private and Public Variables.

Private variables are those variables that are only available in function scope. example,

function sayHello() {
    const hello = "Hello World"; // private method
}
var value = sayHello()
console.log(value.hello);

// output will be:- 
// Undefined

here we got an undefined because hello is defined in scope of sayHello() function, so it will not be accessible outside it's scope.

image.png

So, when JS execute console.log(value), sayHello() is no longer available in memory, that's why value.hello is undefined.

To access private variable outside function scope, we can do two things,

  • make a local function which has access to the private variable, and return that function. (Closure)
  • Return all the private variables that you want to access outside function's scope in an object. (Factory Function)

Public Variables are variables that can be accessible outside the function scope.

Closure

Closures are functions through which we can access variables of outer scope.

a closure gives you access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

function closure() {
    const example = "This is closure";
    let dispclosure = () => { return example };
    return dispclosure; // closure function
}

In the above code, variable example is in local scope of closure(), to access this variable outside the closure() scope, we have created another function dispclosure() which is lexically scoped to closure(), In dispclosure() we have returned variable example. And we have returned reference to the dispclosure function. So example will be accessible to us even though it is locally scoped.

Here dispclosure is closure function.

So when we write,

const value = closure();
console.log(value);
// output will be: - 
// [Function: dispclosure]

Now value will be reference to dispclosure function.

console.log(value());
// output will be: - 
// This is closure

Now as value is reference to dispclosure function, when value is called i.e. value() it will return example variable.

What if when we write closure()() ?

const value = closure()();
console.log(value);
// output will be: - 
// This is closure

Now what happened here, let's try to understand through an diagram.

image.png

So value will be,

image.png

Let's see what happens inside stack memory while executing this statement,

image.png

Another example of closure

const counterCreator = () => {
  let count = 0;
  return () => {
    console.log(count);
    count++;
  };
};

const counter = counterCreator();

counter(); // 0
counter(); // 1
counter(); // 2
counter(); // 3

Keep in mind, counter() is calling the return value of counterCreator. As above, the function counter is a closure. It has access to the variable count and can both print and increment it, but there is no other way for our program to access that variable.

To go more deep into scope and closure read this article or watch this video

Factory Function

Before moving to factory function we need to understand the real issue with object constructor.

What if we don't use 'new' keyword while object creation, let's see

function Fubar(foo, bar) {
    this._foo = foo;
    this._bar = bar;
}

Fubar.prototype.contains = "This is Prototype"

var fubar = Fubar("Foo", "Bar");

console.log(fubar); // Error
console.log(_foo); // Foo

if we don't use new keyword, JS sets this to global scope, it's just like we are calling an ordinary function whose scope is global

To understand more about issue with object constructor read this

So to solve this problem we use Factory Functions.

Instead of using new keyword, we return an object which has variables and functions that we want to make as public, By using factory method we can achieve abstraction as per user's requirement.

const personFactory = (name, age) => {
    this.name = name;
    this.age = age;
    const sayHello = () => { console.log(`Hello ${this.name}`) };
    return { name, age, sayHello };
}

const rushi = personFactory('Rushi', 20);
rushi.sayHello(); // Hello Rushi

To read more about factory functions read this

Inheritance in Factory Functions

const Person = (name, age) => {
    const getname = () => name;
    const getage = () => age;
    return { getname, getage };
}

const Nerd = (name, age) => {
    const { getname } = Person(name, age);
    const sayHello = () => {
        console.log(`Hello ${getname()}`);
    }
    return { getname, sayHello };
}

const jeff = Nerd('jeff', 21);
console.log(jeff.getname());
jeff.sayHello();

please do share this blog if you like it.

Thanks !!

Did you find this article valuable?

Support J_Dheeraj by becoming a sponsor. Any amount is appreciated!