OMG. Just reading the word 'Closures' makes me panic. I mean I have used a LOT of JavaScript in my projects, done callbacks 4 or 5 layers deep, basically all mind bending stuff. But never got my hands on closures. But it has always been in the back of my mind that one can never be true JS programmer without closures.
I did try to learn them, at many points in time, but failed miserably. All I could see was some weird syntax comprising of nested functions and parentheses. I SO wanted to master this!
Turns out, before closures, one must know what is Lexical Scope, which I do, now. So what is a closure? Answer: The function inner() from the earlier post! Yes, we have already implemented a closure without our knowledge.
Let me quote a formal definition of a closure from HFJS: "Closure, noun: A closure is a function together with a referencing environment."
A function will have local variables in it's body which are declared and initialized in the function. But a function may also have referenced variables which were declared outside the itself. They are called free variables of the function.They may be in an enclosing scope or global.When we have an environment that provides value for all the free variables, we say we closed the function. And when we take the function and the environment together, we have a closure.
So in the previous post, inner() was the function, and myVar, it's free variable, which was declared in outer(). We called inner() from outside the outer() function, however, surprisingly, it could still access myVar, which should have gone out of scope by now. But no, it is a part of the environment and hence was not killed. It was in the closure.
Why Closures?
The free variables (myVar in our case) are accessible only to the closure. It cannot be accessed by any other code. Hence closures can be used whenever there is a need to pack together a function and the data it uses, together privately. The data is persisted till the page is reloaded.
Closures contain the actual environment, not a copy:
Many people (and I must admit, me included) think that closure will have a copy of the enclosing environment. This is not true. Closures reference the actual, live variables in the enclosing scope.
var closure = function () {
var greeting = "Hi";
setTimeout(function() {
document.write(greeting);
}, 1000)
greeting = "Hello";
}
closure();
In this code, first we set the environment variable greeting to Hi! and then create a closure which is passed to setTimeout to be executed after 1 second. Then, we change the value of greeting. What is printed is the changed value, not the one that was there when the closure was created.
Ways to create closures
"Returning a function from a function isn’t the only way to create a closure. You create a closure whenever you have a reference to a function that has free variables, and that function is executed outside of the context in which it was created".
1. Passing a function to another function:
function closureCreator() {
var local = 4;
setTimeout(function() {
alert(local);
}, 1000);
}
closureCreator();
So in this code above, closureCreator() creates a function which has a free variable local and passes it to setTimeout. Thus, the inner function results in a closure being created.
2. Creating a closure using event handler:
Consider the following code:
window.onload = function() {
var greeting = "Hello";
var but = document.getElementById("but");
var div = document.getElementById("message");
but.onclick = function () {
div.innerHTML = greeting;
}
}
First, we define handler for window.onload. Then, in that handler we define some DOM references and a greeting variable.
Then, we create a handler for button click. In this handler, we access the DOM reference for div and greeting variable. This function will actually be called when button is clicked, which will be out of context. Thus, it will result in a closure.
Conclusion
I am starting to feel the heat! Whoever says that JavaScript is just a browser script used to do some client side validations, needs to look at this! This post will be updated as and when I get more clear about the idea of closures. I will end this post with a definition of closure in my words:
"Whenever a function containing free variables, is executed out of the score in which it was created, a closure is born. That closure contains the function as well as all the free variables referenced in the function."
I did try to learn them, at many points in time, but failed miserably. All I could see was some weird syntax comprising of nested functions and parentheses. I SO wanted to master this!
Turns out, before closures, one must know what is Lexical Scope, which I do, now. So what is a closure? Answer: The function inner() from the earlier post! Yes, we have already implemented a closure without our knowledge.
Let me quote a formal definition of a closure from HFJS: "Closure, noun: A closure is a function together with a referencing environment."
A function will have local variables in it's body which are declared and initialized in the function. But a function may also have referenced variables which were declared outside the itself. They are called free variables of the function.They may be in an enclosing scope or global.When we have an environment that provides value for all the free variables, we say we closed the function. And when we take the function and the environment together, we have a closure.
So in the previous post, inner() was the function, and myVar, it's free variable, which was declared in outer(). We called inner() from outside the outer() function, however, surprisingly, it could still access myVar, which should have gone out of scope by now. But no, it is a part of the environment and hence was not killed. It was in the closure.
Why Closures?
The free variables (myVar in our case) are accessible only to the closure. It cannot be accessed by any other code. Hence closures can be used whenever there is a need to pack together a function and the data it uses, together privately. The data is persisted till the page is reloaded.
| A closure: function with it's environment, packed together. |
Closures contain the actual environment, not a copy:
Many people (and I must admit, me included) think that closure will have a copy of the enclosing environment. This is not true. Closures reference the actual, live variables in the enclosing scope.
var closure = function () {
var greeting = "Hi";
setTimeout(function() {
document.write(greeting);
}, 1000)
greeting = "Hello";
}
closure();
In this code, first we set the environment variable greeting to Hi! and then create a closure which is passed to setTimeout to be executed after 1 second. Then, we change the value of greeting. What is printed is the changed value, not the one that was there when the closure was created.
Ways to create closures
"Returning a function from a function isn’t the only way to create a closure. You create a closure whenever you have a reference to a function that has free variables, and that function is executed outside of the context in which it was created".
1. Passing a function to another function:
function closureCreator() {
var local = 4;
setTimeout(function() {
alert(local);
}, 1000);
}
closureCreator();
So in this code above, closureCreator() creates a function which has a free variable local and passes it to setTimeout. Thus, the inner function results in a closure being created.
2. Creating a closure using event handler:
Consider the following code:
window.onload = function() {
var greeting = "Hello";
var but = document.getElementById("but");
var div = document.getElementById("message");
but.onclick = function () {
div.innerHTML = greeting;
}
}
First, we define handler for window.onload. Then, in that handler we define some DOM references and a greeting variable.
Then, we create a handler for button click. In this handler, we access the DOM reference for div and greeting variable. This function will actually be called when button is clicked, which will be out of context. Thus, it will result in a closure.
Conclusion
I am starting to feel the heat! Whoever says that JavaScript is just a browser script used to do some client side validations, needs to look at this! This post will be updated as and when I get more clear about the idea of closures. I will end this post with a definition of closure in my words:
"Whenever a function containing free variables, is executed out of the score in which it was created, a closure is born. That closure contains the function as well as all the free variables referenced in the function."
This comment has been removed by the author.
ReplyDeleteThanks, Arundhati!
ReplyDelete