If you have read my article on Variable Hoisting In JavaScript! then you know that there is only function scope in JavaScript and no block scope. We take this understanding a step further and explore closures now!
To understand closures, let us first understand what inner functions are. Take a look at the function innerFn below:
Functions are data in JavaScript and a function could contain data and hence another function too. In this case, outerFn contains innerFn and the innerFn becomes our inner function as it is scoped within outer function outerFn. Because there is function scope in JavaScript, the following points apply:
- The variable x is declared in the global space (window) and therefore is accessible everywhere.
- The variable y is declared inside outer function (outerFn) and hence is accessible everywhere inside the outer function (outerFn). This implies it is accessible inside the inner function (innerFn) too.
- The variable z is declared inside the inner function (innerFn) and hence is accessible inside the inner function and not outside of it.
- The inner function (innerFn) will always have access to the outside world as it is global to it. For example, it will have access to the content of outer function and global space. If inner function contains another function, say innerFn2 then the innerFn would not have any access to the content of innerFn2 but innerFn2 would have access to the content of innerFn, outerFn and the global space.
Inner functions are the private functions:
You can access outerFn from global space because it is declared in the global space. You can however not access innerFn from the global space, simply because innerFn is scoped within outerFn (remember function scope). Creating inner functions is therefore the JavaScript way of creating private functions. In this case, innerFn is a private function to outerFn and it cannot be accessed outside outerFn.
Difference between inner functions and closures:
So, what are closures then? Are they simply the inner functions? The answer is both yes and no! It should be noted that all closures are inner functions but all inner functions are not closures!
What makes an inner function a closure?
Take a look at the code snippet below:
With the above example, we have just broken the encapsulation. We accessed the innerFn from global space although innerFn was scoped to outerFn and not accessible outside. We did it by simply returning the reference of the function.
There is another way to break this encapsulation. Below is how you can do it as well:
This time we did it using a global variable. The global variable can be accessed anywhere and we used it to our advantage by storing the reference of innerFn inside it and then accessing the function outside. And yes, we again broke the so called encapsulation.
How does this breaking of encapsulation compliment our discussion on closures? When you break this encapsulation and call an inner function from outside its enclosing function, the inner function becomes a closure!
Most important characteristic of closures:
In the above example when you call outerFn() and outerFn finishes its execuation, the variables inside the function are destroyed soon after. This implies that the variable y which is scoped within outerFn will be destroyed soon after it goes out of scope i.e. the outerFn has completed its execution.
What happens when you call the myInnerFn() soon after(line-26)? Note that inside innerFn, we access the variable y (line-18). Do we get the reference of y, as it is supposed to have been destroyed already after outerFn completed its execution? The answer is yes! The innerFn will have the reference of y although the variable is supposed to be already out of scope by now. The reason is that closures maintain the references of the variables of their enclosing function (outerFn) even though the enclosing function has already completed execution and the variables are supposed to be gone! This is the beauty of closures.
Closures therefore are the inner functions that are accessed outside their enclosing functions and retain the references of variables in their enclosing function, even though the enclosing function has completed its execution and the variables are scoped out.
If you think closely, the outerFn, which is declared in the global space is also an inner function. Do you agree?



No comments:
Post a Comment