Closures
Credit : Edward Huang
Closures and Prototypal Inheritance are one of the two pillars of JavaScript. Closures are basically the combination of functions and the lexical environment or scope.
A closure is a combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). Source: (MDN)
Scope simply defines the area where functions and variables are accessible. Lexical scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope. Functions are first-class objects in JavaScript meaning they are an entity that supports all other properties inherent to other entities such as being assigned a variable, passed around as a function argument, or returned from a function. Closures allow a function to access variables from an enclosing scope or environment even after it leaves the scope in which it was declared. Let’s look at an example below.
function a () { // Declare the first function a
let grandpa = 'grandpa' //a variable that holds a string grandpa
return function b () { //Return another function in a function(High order function)
let father = 'father' // a variable that holds a string grandpa
return function c () { //Return another function in a function(High order function)
let son = 'son'
return `${grandpa}, ${father}, ${son}` // A template string that returns a string
}
}
}
//Let's call each of the functions above
a(); //Returns function b()
a()(); // Returns function c()
a()()(); // Returns grandpa,father,son
The result of the code above is :
When the function a () gets called **first it gets popped onto the stack and we create a variable environment that contains the variable grandpa. Let us visualize this concept below.
Assuming we have a box called closures box. When the first function is called and popped off the stack the variable stored is moved into the box closure box
In JavaScript, we have a memory heap which is simply where memory is allocated, and whenever a variable is no longer needed it gets garbage collected but in this example, the variable grandpa is not removed by the garbage collector because it is being referenced by something which in this case is function c().
The next b() function gets called and added onto the stack and once it gets popped off the stack the father gets placed into the special closure box since it is being referenced by function c().
Now function c () gets popped onto the stack, It’s a variable environment or scope that only has the variable son but doesn’t have father and grandpa in it. When we try to return the function, the JavaScript engine will look into the special closure box and allow the function to return the variables grandpa and father.
Let’s look at another example:
Let’s make use of an example with a Web API setTimeOut
// Second Example
function returnInFiveSeconds () {
const returnOnTime = 'Hi, I am there now';
setTimeout(function () {
console.log(returnOnTime);
}, 5000);
}
returnInFiveSeconds();
We have a function in setTimeout and if we can remember setTimeout gets sent to the Web API to start a timer in our case 5 seconds and when the timer expires it get sent to the Callback Queue where it will wait until our Call Stack is empty and returnInFiveSeconds() has being popped off the stack, the Event Loop will take the setTimeout to the Call Stack and run the console.log(returnOnTime). Technically the variable returnOnTime should have being popped off the stack before we got to the setTimeout method but because of closures the functions was still able to access the variable even after it was popped off the stack.
Closures and Encapsulation
Encapsulation describes the idea of bundling data and methods that work on that data within one unit.
Encapsulation refers to the bundling of data with the methods that operate on that data, or the restricting of direct access to some of an object's components. Source: (Wikipedia).
We can use closure to hide and store data in a separate scope and use it only when deem fit.
Let’s write an example with some code.
const makeABombButton = () => {
let timeWithoutDestruction = 0;
const passTime = () => timeWithoutDestruction++;
const totalPeaceTime = () => timeWithoutDestruction;
const launch = () => {
timeWithoutDestruction = -1;
return 'bomb goes boooommmmmmmm';
}
setInterval(passTime, 1000);
return {
totalPeaceTime: totalPeaceTime
}
}
const bombGoesOff = makeABombButton();
bombGoesOff.totalPeaceTime()
bombGoesOff.launch(); // THIS WON'T RUN AT ALL
If we run this in the dev tools we will get;
totalPeaceTime() is accessible as it is contained in the object returned while launch() isn’t as it is properly encapsulated. This is made possible with closures and encapsulation and can be used in many real life use cases where you don’t want users to have access to some functions or properties in your API or Code.
Prototypal Inheritance
What is Prototypal Inheritance
JavaScript is an protoypal-based, Object Oriented Programming. After the ES6 updates, JavaScript allowed for “prototypal inheritance”, meaning that objects and methods can be shared, extended, and copied.
The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object. Traditionally, in order to get and set the [[Prototype]] of an object, we use Object. getPrototypeOf and Object. Source: (GeekforGeeks.org)
Credit: (GeekforGeeks.org)
In JavaScript, everything is an object. We use javascript prototype to add new properties and methods to an existing object constructor. Prototypical inheritance allows us to reuse the properties or methods from one JavaScript object to another through a reference pointer function.
All JavaScript objects inherit properties and methods from a prototype:
- Date object inherit from Date.prototype
Array
object inherit from**Array.prototype**
- `Persons
object inherit from **
Person.prototype`**
The Object.prototype is on top of the prototype chain and the rest all inherit from Object.prototype
chain
• __proto__
is another keyword that can help us determine the parent/prototype of any object(even array or function) in javascript.
If we run array.__proto__
on our chrome dev tools. We can see all the properties of an array.
Let’s proceed to work with some examples
Example 1
let dragon = {
name: 'Tanya',
fire: true,
fight() {
return 5
},
sing() {
if (this.fire) {
return `I am ${this.name}, the breather of fire`
}
}
}
let lizard = {
name: 'Kiki',
fight() {
return 1
}
}
lizard.__proto__ = dragon;
console.log(dragon.isPrototypeOf(lizard)); // true
console.log(lizard.fire) // true
console.log(lizard.sing()) // I am Kiki, the breather of fire
const lizardFire = dragon.sing.bind(lizard)
console.log(dragon.hasOwnProperty(name)) // true
console.log(lizardFire()) // I am Kiki, the breather of fire
- Lets make an object dragon with different function and properties and another object lizard with the same properties.
- We have the
isPrototypeof
method that checks if an object exists in another object's prototype chain. - The
bind()
method creates a new function that when called as it’sthis
set to a provided value. - The
hasOwnProperty()
method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).
Example 2
const car = {
name: 'Toyota',
make: 'Camry',
year: 2013,
}
const owner = {
firstName: 'Teslim',
lastName: 'Odumuyiwa',
}
car.__proto__ = owner;
console.log(owner.__proto__) // we receive the owner object
console.log(owner.__proto__.__proto__) // we receive the base constructor object
console.log(owner.__proto__.__proto__.__proto__) // we get null
The output is :
__proto__
returns the parent object of our current object that it inherits its properties from.- But if we further access the
__proto__
property of their outputs then we get the constructor object that is the base unit of arrays, functions, objects etc in JavaScript. - We cannot go any further back than the Object property in the prototypal chain. Behind that we only receive
null
.
Wrapping Up
Closures and Prototypal Inheritance are two important pillars to learn before diving into Object-Oriented Programming and Functional Programming. Closures control what is and what isn’t a scope in a particular function and Prototypal Inheritance is commonly used in web frameworks to help allow the sharing of common behavior and state among familiar components
Further Reading:
Closures - MDN
Inheritance and the prototype chain - MDN
Understanding and Using Prototypical Inheritance in JavaScript - Educative.io