Skip to main content

Come Closure in Javascript

What is a closure?

If we want to derive a definition,we can say,
A closure is a feature of Javascript where inner function has access to the outer (enclosing) function’s variables—scope chain. This scope chains means inner function has:
  • access to its own scope (variables defined between its curly brackets and its parameters),
  • access to the outer function’s variables and parameters, 
  • access to the global variables.
Now we will look into it in detail. Consider following example
var globalVar = "xyz"; function outerFunc(outerArg) { var outerVar = 'Alex'; function innerFunc(innerArg) { var innerVar = 'Chris'; console.log("globalVar = " + globalVar); console.log("outerArg = " + outerArg); console.log("innerArg = " + innerArg); console.log("outerVar = " + outerVar); console.log("innerVar = " + innerVar); } innerFunc(456); } outerFunc(123);
In this example, inside the inner function innerFunc, we have access to
  • its own scope(innerVar and innerArg)
  • outer function outerFunc variable(outerVar) and parameter(outerArg)
  • and global variable(globalVar)
Remember : In hoisting, we have seen, when a function executes and it encounter a variable,it looks for it in its own scope first, if it doesn't find, it searches in outer function's scope and finally in global scope.

Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope. e.g.
function foo() { var a = 2 function bar() { console.log(a) // 2 } bar() } foo()
Closure has access to outer function's scope, even after outer function is return. For e.g.
function outer(a) { var b = 10; function inner() { var c = 20; console.log(a+b+c); } return inner; } var add = outer(5); // inner function will be assigned to add console.log(add); // ƒ inner() { var c = 20;
console.log(a+b+c); } console.log(typeof add); // function add(); // output 35
The inner function can access the variables(here b) of the enclosing function and the parameter(here a) due to closures in JavaScript. So inside the inner function we have value of a = 5 and b=10, when the outer(5) was executed.Since we have values of a and b due to closure, also c is a inner variable so Javascript engine can calculate a+b+c which is equal to 35.
Let us then consider code which brings closure into full light:
function foo() { var a = 2 function bar() { console.log(a) } return bar } var baz = foo() baz() // 2 
After we execute foo(), we assign the value it returned (our inner bar() function) to a variable called baz, and then we actually invoke baz(), which of course is invoking our inner function bar().After foo() executed, normally we would expect that the entirety of the inner scope of foo() would go away.But the "magic" of closures does not let this happen. That inner scope is in fact still "in use", and thus does not go away. Who's using it? The function bar()itself.By virtue of where it was declared, bar()has a lexical scope closure over that inner scope of foo(), which keeps that scope alive for bar() to reference at any later time.
bar() still has a reference to that scope, and that reference is called closure.

Functions can be passed around as values, and indeed invoked in other locations, are all examples of  closure. Consider following code:
function foo() { var a = 2; function baz() { console.log(a); // 2 } bar(baz); } function bar(fn) { fn(); // here is the magic of closure! } 

foo();
We pass the inner function baz over to bar, and call that inner function (labeled fn now), and when we do, its closure over the inner scope of foo() is observed, by accessing a.

Closure with loop

The most common example used to illustrate closure involves for-loop.
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() { console.log(i); }, i * 1000); }

Looking at this code snippet, we would normally expect the numbers "1", "2", .. "5" would be printed out, one at a time, one per second, respectively.
But actually, if you run this code, you get "6" printed out 5 times, at the one second interval.
Firstly, let's understand where 6 comes from. The terminating condition of the loop is when i is not <=5. The first time that's the case is when i is 6. So, the output is reflecting the final value of the i after the loop terminates.The timeout function callbacks are all running after the completion of the loop.

What's missing is that we are trying to imply that each iteration of the loop "captures" its own copy of i, at the time of the iteration. But, the way scope works, all 5 of those functions, though they are defined separately in each loop iteration, all are closed over the same shared global scope, which has, in fact, only one i in it.

So we got the issue that each time for is running its not keeping the copy of each i value during iteration. We can bind each i by passing it inside the setTimeout scope. Here I have used IIFE where I am passing value of i.

The use of an IIFE inside each iteration created a new scope for each iteration, which gave our timeout function callbacks the opportunity to close over a new scope for each iteration, one which had a variable with the right per-iteration value in it for us to access.
for (var i = 1; i <= 5; i++) { (function(j) { setTimeout(function timer() { console.log(j); }, j * 1000); })(i); }

Now we will get the expected output. i.e. 1,2, ... 5 each at one-second interval.

Hope this article was helpful. Subscribe and leave your comments to support.
Thank you!!

Comments

  1. Great Article. Thank you for sharing! Really an awesome post for every one.

    IEEE Final Year projects Project Centers in Chennai are consistently sought after. Final Year Students Projects take a shot at them to improve their aptitudes, while specialists like the enjoyment in interfering with innovation. For experts, it's an alternate ball game through and through. Smaller than expected IEEE Final Year project centers ground for all fragments of CSE & IT engineers hoping to assemble. Final Year Project Domains for IT It gives you tips and rules that is progressively critical to consider while choosing any final year project point.

    Spring Framework has already made serious inroads as an integrated technology stack for building user-facing applications. Spring Framework Corporate TRaining the authors explore the idea of using Java in Big Data platforms.
    Specifically, Spring Framework provides various tasks are geared around preparing data for further analysis and visualization. Spring Training in Chennai

    ReplyDelete

Post a Comment

Popular Posts

Javascript Hoisting Interview Question and Answers - 5

In this post,I have tried to cover all the types of possible interview questions and answers on hoisting. If you are not familiar with the hoisting, I would highly recommend you to go to my post on hoisting. Once you are comfortable with the topic, you can attempt these questions. Understanding the type of question will help you to answer. I have provided the hint after each question. All the answers are given at the end of the post.
//Question 1 console.log('bar:', bar) bar = 15 var foo = 1 console.log(foo, bar) var bar Hint: Basics of hoisting //Question 2 var foo = 5 console.log('foo:', foo) var foo; var bar = 10; var bar; console.log('bar:', bar) var baz = 10 var baz = 12 console.log('baz:', baz) Hint: Basics of hoisting //Question 3 function foo() { function bar() { return 5 } return bar() function bar() { return 10 } } console.log(foo()); Hint: Think what happens if two functions wit…

Javascript Closure Interview Questions and Answers - 6

Here in the post, I have posted all the possible interview questions and answers on closure. If you are not familiar with the closure, I would highly recommend you to go to my post onclosure. Once you are comfortable with the topic, you can attempt these questions. All the answers are given at the end of the post.

//Question 1 function foo() { var a = 5 function bar() { console.log(a) } return bar; } var baz = foo() baz()
// Question 2 function outer(a) { var b = 2 function inner() { var c = 5 console.log(a * b * c) } return inner; } var multiply = outer(5) multiply()
// Question 3 const arr = [10, 20, 30, 40, 50] for (var i = 0; i < arr.length; i++) { setTimeout(function() { console.log('Index: ' + i + ', element: ' + arr[i]) }, 1000) }
// Question 4 for (var i = 0; i < 5; i++) { setTimeout(function(i) { return function() { console.log('The value of…