Closures and Factory Functions
Function call, Private and Public variables, Closures, 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.
Now let's look in the memory,
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.
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.
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.
So value will be,
Let's see what happens inside stack memory while executing this statement,
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.