Hello everyone π, I hope you are doing well.
In this post I will explain what closures are using examples as well so that you too can use them to write your code better.
LEXICAL SCOPE βοΈ
Before directly explaining what closures are, it is appropriate to explain the concept of scope and lexical scope.
The scope of a function refers that area of code where its variables are "visible" and can be used.
If another function is created within one function, another internal scope will then be created, and so on: this is called a scope chain.
Lexical scope, also called static scope, refers to when the location of a function's definition determines which variables you have access to.
E.g. :
const life = () => {
const pastEvents = 'past'
//console.log(actualEvents) this will create an error because that inner variable is not accesible here
const present = () => {
const actualEvents = 'present'
console.log(pastEvents, actualEvents)//ok
//console.log(futureEvents) same for this one
const future = () => {
const futureEvents = 'future'
console.log(pastEvents, actualEvents, futureEvents)//ok
}
future()
}
present()
}
life()
/*
Outputs:
past present
past present future
*/
As you can see, in a nested group of functions the inner functions have access to the variables and other resources of their parent scope.
CLOSURES πͺ
Let's make some changes to the code from before:
const life = () => {
const pastEvents = 'past'
const present = () => {
const actualEvents = 'present'
console.log(pastEvents, actualEvents)
const future = () => {
const futureEvents = 'future'
console.log(pastEvents, actualEvents, futureEvents)
}
return future
}
return present
}
const newFunc = () => {
//different scope
const newLife = life()
const future = newLife()
future()
}
newFunc()
/*
Outputs:
past present
past present future
*/
New functions created within the newFunc function have access to the variables pastEvents, actualEvents and futureEvents even if they are in another scope.
This is because the future and present functions are closures: when they are assigned to variables (in our case newLife and future) they close over (from here the term closure) the variables of their lexical scope.
Due to this the closures are memory efficient saving code repetitions.
Here another example:
const addTo = x => y => x + y //x = outer func; y = inner.
const addToTen = addTo(10)
addToTen(3) // returns 13
Another benefit they bring is that of data encapsulation:
const createCounter = () => {
let count = 0
return {
increment() {
count++
},
decrement() {
count--
},
showCount() {
console.log(count)
}
}
}
const myCounter = createCounter()
for(let i = 0; i < 100; i++)
myCounter.increment()
myCounter.decrement()
console.log(myCounter.count)//returns undefined
myCounter.showCount()//returns 99
In this way, the count variable is private and can be accessed only through proper functions written by the developer.
CONCLUSIONS
If you have come this far in reading, I thank you. If you liked the post please leave a like and check out my other posts π.
Top comments (0)