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

Post a Comment

Popular Posts

Javascript Interview Question and Answer - 1

In this article we are going to discuss 2 javascript interview question and their answers.These questions are highly asked in the Javascript interviews.

Disclaimer: - You might have different solution working with all test cases for both the problems.

So lets discuss the first question.This question is to test your ability in terms javascript object knowledge and your logical thinking.

Q1. You have been given a nested object "Person" which has one of the property as "password".Write a generic function to change the value of all the "password" property to "*****". Object is nested and may contain other object with property "password" and so on. Here is a sample object.

var Person = {
     name: 'Alex',
     age : 40,
    password : 'abc',
    x : {
       name : 'Chris',
       password: 'abcd',
       y : {
          name : 'Mike',
          password: 'abcd',
         },
     }
.
.
}

Before we …

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…