ByPaul Upendo

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, thelet keyword with curly braces among others. We mainly have two variations of scope: theglobal scope andlocal scope.
var initialBalance=0// Global Scopefunctiondeposit(amount){/** * Local Scope * Code here has access to anything declared in the global scope */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// Variable declared in the Global Scopefunctionwithdraw(amount){var balance// Variable declared in function scope balance=parseInt(initialBalance)-parseInt(amount)return balance}console.log(initialBalance)// Will output initialBalance value as it is declared in the global scopeconsole.log(balance)// ReferenceError: Can't find variable: balanceJavaScript’s Lexical Scope is determined during thecompile 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// Global Scopefunctionwithdraw(amount){/** * Local Scope * Code here has access to anything declared in the global scope */var balance=parseInt(initialBalance)-parseInt(amount)const actualBalance=(function(){constTRANSACTIONCOST=35return balance-TRANSACTIONCOST/** * Accesses balance variable from the lexical scope */})()// Immediately Invoked Function expression. IIFE// console.log(TRANSACTIONCOST) // ReferenceError: Can't find variable: TRANSACTIONCOSTreturn 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.
functionperson(){var name='Paul'// Local variablevar actions={speak:function(){// new function scopeconsole.log('My name is ', name)/** * Accessing the name variable from the outer function scope (lexical scope) */}}// actions object with a functionreturn actions/** * We return the actions object * We then can invoke the speak function outside this scope */}person().speak()// Inner function invoked outside its lexical ScopeA 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.
varModule=(function(){var foo='foo'// Private PropertyfunctionaddToFoo(bam){// Private Method foo= bamreturn foo}var publicInterface={bar:function(){// Public Methodreturn'bar'},bam:function(){// Public MethodreturnaddToFoo('bam')// Invoking the private method}}return publicInterface// Object will contain public methods})()Module.bar()// barModule.bam()// bamFrom 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 asetTimeout or any kind of callback. The function still remembers the lexical scope because of the closure.
functionfoo(){var bar='bar'setTimeout(function(){console.log(bar)},1000)}foo()// barClosure and loops
for(var i=1; i<=5; i++){(function(i){setTimeout(function(){console.log(i)}, i*1000)})(i)}/*** Prints 1 through 5 after each second* Closure enables us to remember the variable i* An IIFE to pass in a new value of the variable i for each iteration* IIFE (Immediately Invoked Function expression)*/for(let i=1; i<=5; i++){(function(i){setTimeout(function(){console.log(i)}, i*1000)})(i)}/*** Prints 1 through 5 after each second* Closure enabling us to remember the variable i* The let keyword rebinds the value of i for each iteration*/I bet we now have an understanding of closures and can do the following:
Until next time, happy coding.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to usingMarkdown to format your answer.
You can type!ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to ourPrivacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.