Originally published by Ashutosh Singh  at dzone.com

“Writing in ECMAScript language without understanding closure is like writing Java without understanding classes” — Douglas Crockford, father of JSON.

In this piece, we are going to discuss closures and lexical scoping in JavaScript. Understanding closures leads to a better understanding of programming itself. If you are planning on becoming a professional programmer, questions regarding closures and their applications are widely asked during technical interviews and can be really helpful to you.

If you are a JavaScript developer, chances are you already using closures and just don't know it. There are so many complex examples out there that just confuse you when you try to learn closures, so I’ll be using the simplest examples I could find and by the end of this piece, you should have a basic understanding of what closures are. Let's get started.

Lexical Scoping

Before we can discuss closures, we should have a basic understanding of the scope and lexical scope. JavaScript has lexical scoping with function scope, which means each function creates a new scope.

Function Scope

Basically, in JavaScript, there is Global Scope and Local Scope.

  • Global Scope: There is only one Global Scope in a Javascript Document i.e. area outside all the functions and how you can identify a global scope is that the variable defined in the global scope can be accessed anywhere in the code.
  • Local Scope: Variables declared inside functions are local to the function and is bound to the corresponding local scope. Those variables cannot be accessed outside the functions.

Let's see an example:

// global scope
let iHaveGlobalScope=`I can be accessed from anywhere in this document`

function localScope()
{
console.log(iHaveGlobalScope)

// lcoal scope1
let iHaveLocalScope=`I am bound to the local scope of function localScope`
}

console.log(localScope())
//I can be accessed from anywhere in this document

console.log(iHaveLocalScope)
//ReferenceError: iHaveLocalScope is not defined

The variable iHaveGlobalScope is declared in the global scope and therefore can be accessed even from within the function localScope(), but when I try to console log the variable, iHaveLocalScope, outside the function or outside the local scope, it throws a Reference Error at runtime.

The local scope can be further divided into function scope and block scope. The concept of block scope was introduced in ES6 together with new ways to declare variables — const and let.

Function Scope and Block Scope

Whenever you declare a variable inside a function, the variable is bound within the function, and you can’t access it outside the function. var is the keyword to define a variable for function-scope accessibility.

function functionScope(){
var iHaveFunctionScope=something something mj
console.log(iHaveFunctionScope)
}
functionScope()
//something something mj

console.log(iHaveFunctionScope);
//Reference Error

Now, you might ask, “if it gives an error even if you use let or const, why is only var associated with function scope?” The thing is,let and const are used to define block scope, and before ES6, JavaScript didn’t have block scope orletand const.

A block scope is the area within ifswitch conditions or for and whileloops. Simply put , whenever you see {curly brackets}, it is a block.

A block scope the area within if , switch  conditions or for  and while  loops. Simply put, whenever you see curly brackets, it is a block. 

Let’s see an example:

function scope(){
if(true){
var scope1 =I have function Scope
let scope2 = I have block scope
const scope3 =I also have block scope
}
console.log(scope1)
console.log(scope2)
console.log(scope3)

}
scope()

//I have function Scope

//ReferenceError: scope2 is not defined

//ReferenceError: scope3 is not defined

Now, you might expect that none of the log commands should work, but as you can see, that is not the case with var; variables defined with var inside ifswitch conditions or for and while loops can be accessed globally and are part of global scope. Therefore, it is better practice to use let and constwith them.

Lexical Scope

Finally, we have reached the true purpose of this post. Again, a point to remember: Javascript has lexical scoping with functions scope.

In simple words, this means the child’s scope has access to the variables defined in the parent’s scope. For instance, If I were to define a function and declare a variable inside it, and inside the very same function, define another function, then I should be able to use that variable inside the inner function because of lexical scoping. Let’s see an example:

function outerFunction() {
var variable1 = ‘ney vatsa’
const variable2 = ‘shashank jha’
let variable3 = ‘huda’

function innerFunction() {
    console.log(variable1)
    console.log(variable2)
    console.log(variable3)
}
innerFunction()

}
outerFunction()

// ney vatsa
//shashank jha
//huda

It can be seen from the example that the variables declared inouterFunction()are accessed by innerfunction(); this is lexical scoping.

The scope of variables is defined by their position in the code. In order to resolve variables, JavaScript starts at the innermost scope and searches outwards, until it finds the variable it was looking for. In the above example, Javascript first searches for variables inside innerFunction(), and when it doesn’t find it, it goes outside i.e outerFunction().

Lexical scoping is better because we can easily figure out the value of a variable from the code, whereas in dynamic scoping, the meaning of a variable can change at runtime, which makes it complex to understand.

So, we have successfully understood what lexical scoping is. Now, let’s look at closures where lexical scoping is actually used.

Closures

According to the Mozilla Development Network(MDN) :

“A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.”

First, let’s look at a simple example to start:

var outerFunction = function () {
let variable1 = “Example of closure”

var innerFunction = function () {
    console.log(variable1)

}
return innerFunction;

}

var newFunction = outerFunction()
newFunction()
//Example of closure

The main point to think here is outerFunction() returns innerFunction() , so thenewFunction()is in factinnerFunction(), but we didn’t return variable1. Still, it is a part of newFunction(), so where does the value of variable1 come from if outerFunction() is already returned i.e. finished executing.

This accessing of a variable outside the immediate scope will give rise to a closure.

Since variable1 was part of the lexical environment that created innerFunction() , innerfunction()  will have to access it. 

Let’s look at another example:

function add(x) {
return function(y) {
return x + y;
};
}

var addFive = add(5);
var addTen = add(10);

console.log(addFive(10)); // 15
console.log(addTen(10)); // 20

Just FYI, this is a widely used example for closure, and you may find it in many tutorials. Here, we have defined the function add() with a parameter x, which returns another function with parameter y, which returns the sum of x and y.

Now, we create new functions addFive() and addTen() by passing arguments inside the add()function. TheseaddTen() and addFive() are actually closures, and although they have the same function body definition, they store different lexical environments. In addFive() the lexical environment, x is five, while in the lexical environment for addTen(), x is ten.

Closures are a very important part of programming, not only in JavaScript but in all programming languages. They have so many practical applications, such as object data privacy, event handlers, and callback functions.

I hope by now you have a basic understanding of scope in JavaScript. We have covered a brief introduction to lexical scoping and closures in this post. In next post, we will discuss closures in detail and their actual use cases, such as data privacy, call()bind()apply(), event handlers, etc.

Originally published by Ashutosh Singh  at dzone.com

===========================================

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

☞ Svelte.js - The Complete Guide

☞ The Complete JavaScript Course 2019: Build Real Projects!

☞ Become a JavaScript developer - Learn (React, Node,Angular)

☞ JavaScript: Understanding the Weird Parts

☞ JavaScript: Coding Challenges Bootcamp - 2019

☞ The Complete Node.js Developer Course (3rd Edition)

☞ Angular & NodeJS - The MEAN Stack Guide

☞ NodeJS - The Complete Guide (incl. MVC, REST APIs, GraphQL)

☞ Node.js Absolute Beginners Guide - Learn Node From Scratch

#javascript #web-development

A Brief Introduction to Closures and Lexical Scoping in JavaScript
3 Likes9.30 GEEK