This is one of the important features in JavaScript.
Closure means that an inner function always has access to the vars and parameters of its outer function, even after the outer function has returned. The inner function is usually returned from inside the enclosing function.

You have learned that we can create nested functions in JavaScript. Inner function can access variables and parameters of an outer function (however, cannot access arguments object of outer function). Consider the following example.

function OuterFunction() {

    var outerVariable = 1;

    function InnerFunction() {
        alert(outerVariable);
    }

    InnerFunction();
}

In the above example, InnerFunction() can access outerVariable.

Now, as per the definition above, InnerFunction() can access outerVariable even if it will be executed separately.Consider the following example.

Example 1
function OuterFunction() {

    var outerVariable = 100;

    function InnerFunction() {
        alert(outerVariable);
    }

    return InnerFunction;
}
var innerFunc = OuterFunction();

innerFunc(); // 100

In the above example, return InnerFunction; returns InnerFunction from OuterFunction when you call OuterFunction(). A variable innerFunc references the InnerFunction() only, not the OuterFunction(). So now, when you call innerFunc(), it can still access outerVariable which is declared in OuterFunction(). That’s the power of closure!

In other words, one important characteristic of closure is that outer variables can keep their states between multiple calls. Remember, the inner function does not keep a separate copy of outer variables but it references outer variables, that means value of the outer variables will be changed if you change it using inner function.

function Counter() {
    var counter = 0;

    function IncreaseCounter() {
        return counter += 1;
    };

    return IncreaseCounter;
}

var counter = Counter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
alert(counter()); // 4

In the above example, outer function Counter returns the reference of inner function IncreaseCounter(). IncreaseCounter increases the outer variable counter to one. So calling inner function multiple time will increase the counter to one each time.

Example 2: Making Counters

Another example of variable isolation.

function makeCounter(noun) {
  let count = 0;
  return function(){
    count += 1;
    return count + ' ' + noun;
  }
}

const birdCounter = makeCounter("birds");
const dogCounter = makeCounter("dogs");

birdCounter() // '1 birds'
birdCounter() // '2 birds'
birdCounter() // '3 birds'
birdCounter() // '4 birds'
dogCounter() // '1 dogs'
dogCounter() // '2 dogs'
birdCounter() // '5 birds'