Introduction
Learning a new language involves a series of steps, whereas its mastery is a product of patience, practice, mistakes, and experience.
Some developers will have enough knowledge to deliver on features as per a client’s demand, but it takes more than just that to be a good developer.
A good developer is one who takes time to go back and get a good grasp of a language’s underlying/core concepts.
Today we take a deeper look at JavaScript closures and hope that the knowledge you learn will be beneficial in your projects.
A JavaScript Closure is when an inner function has access to members of the outer function (lexical scope) even when executing outside the scope of the outer function.
Therefore, we cannot afford to talk about closure while leaving out functions and scope.
Scope refers to the extent of visibility of a variable defined in a program. Ways to create scope in JavaScript are through: try-catch blocks
, functions
, the let keyword
with curly braces among others. We mainly have two variations of scope: the global scope and local scope.
var initialBalance = 0
function deposit (amount) {
var newBalance = parseInt(initialBalance) + parseInt(amount)
return newBalance
}
Each function in JavaScript creates its own local scope when declared.
This means that whatever is declared inside the function’s local scope is not accessible from the outside. Consider the illustration below:
var initialBalance = 300
function withdraw (amount) {
var balance
balance = parseInt(initialBalance) - parseInt(amount)
return balance
}
console.log(initialBalance)
console.log(balance)
JavaScript’s Lexical Scope is determined during the compile phase. It sets the scope of a variable so that it may only be called/referenced from within the block of code in which it is defined.
A function declared inside a surrounding function block has access to variables in the surrounding function’s lexical scope.
var initialBalance = 300
function withdraw (amount) {
var balance = parseInt(initialBalance) - parseInt(amount)
const actualBalance = (function () {
const TRANSACTIONCOST = 35
return balance - TRANSACTIONCOST
})()
return actualBalance
}
Invoking an inner function outside of its enclosing function and yet maintain access to variables in its enclosing function (lexical scope) creates a JavaScript Closure.
function person () {
var name = 'Paul'
var actions = {
speak: function () {
console.log('My name is ', name)
}
}
return actions
}
person().speak()
A Closure allows us to expose a public interface while at the same time hiding and preserving execution context from the outside scope.
Some JavaScript design patterns make use of closures.
One of these well-implemented patterns is the module pattern, this pattern allows you to emulate: private, public, and privileged members.
var Module = (function () {
var foo = 'foo'
function addToFoo (bam) {
foo = bam
return foo
}
var publicInterface = {
bar: function () {
return 'bar'
},
bam: function () {
return addToFoo('bam')
}
}
return publicInterface
})()
Module.bar()
Module.bam()
From our module pattern illustration above, only public methods and properties in the return object will be available outside the closure’s execution context.
All private members will still exist as their execution context is preserved but hidden from the outside scope.
When we pass a function into a setTimeout
or any kind of callback. The function still remembers the lexical scope because of the closure.
function foo () {
var bar = 'bar'
setTimeout(function () {
console.log(bar)
}, 1000)
}
foo()
Closure and loops
for (var i = 1; i <= 5; i++) {
(function (i) {
setTimeout(function () {
console.log(i)
}, i * 1000)
})(i)
}
for (let i = 1; i <= 5; i++) {
(function (i) {
setTimeout(function () {
console.log(i)
}, i * 1000)
})(i)
}
I bet we now have an understanding of closures and can do the following:
- Illustrate its use cases or identify it in contexts we never knew we used it
- Preserve execution context as we wish
- Implement code in JavaScript’s module pattern
- Use closures in our code, with a clear understanding
Until next time, happy coding.