How do JavaScript closures work?
When I started learning some advanced concepts of JavaScript that time I got to know about closures but when tried to understand it but it was like leave me alone. Then I did some research on it but still, I was getting only theoretical concepts of closures.
So I thought might be I am not alone who don't understand closures so I tried to explain it with examples.
What is Closure in JavaScript?
A closure is a function having access to the parent scope, even after the parent function has closed.
A closure is one way of supporting first-class functions; it is an expression that can reference variables within its scope (when it was first declared), be assigned to a variable, be passed as an argument to a function, or be returned as a function result.
this is the terminology used to explain the closure but I know how hard it is to understand, so let's go by examples.
Example of Closures in JavaScript
function funHelloWorld(value) {
var text = 'Hello ' + value;
var shout = function() { console.log(text); } return shout;
}
var shouted = funHelloWorld('World');
shouted();
The output will be as following screenshot:
As you can see shout function is inside funHelloWorld and its reference to the function. If I will explain this to a programmer using C would think of the function as returning a pointer to a function, and that the variables shout and shouted were each a pointer to a function.
There is a critical difference between a C pointer to a function and a JavaScript reference to a function. In JavaScript, you can think of a function reference variable as having both a pointer to a function as well as a hidden pointer to a closure.
The code has a closure because the anonymous function function() { console.log(text); } is declared inside another function, funHelloWorld() in this example. In JavaScript, if you use the function keyword inside another function, you are creating a closure.
In C and most other common languages, after a function returns, all the local variables are no longer accessible because the stack-frame is destroyed.
In JavaScript, if you declare a function within another function, then the local variables of the outer function can remain accessible after returning from it. This is demonstrated above, because we call the function shouted() after we have returned from funHelloWorld(). Notice that the code that we call references the variable text, which was a local variable of the function funHelloWorld().
function() { console.log(text); } // Output of say2.toString();
The code has a closure because the anonymous function function() { console.log(text); } is declared inside another function, funHelloWorld() in this example. In JavaScript, if you use the function keyword inside another function, you are creating a closure.
In C and most other common languages, after a function returns, all the local variables are no longer accessible because the stack-frame is destroyed.
In JavaScript, if you declare a function within another function, then the local variables of the outer function can remain accessible after returning from it. This is demonstrated above, because we call the function shouted() after we have returned from funHelloWorld(). Notice that the code that we call references the variable text, which was a local variable of the function funHelloWorld().
function() { console.log(text); } // Output of say2.toString();
Looking at the output of shouted.toString(), we can see that the code refers to the variable text. The anonymous function can reference text which holds the value 'Hello World' because the local variables of funHelloWorld() have been secretly kept alive in a closure.
Closure Examples:
This example shows that the local variables are not copied — they are kept by reference. It is as though the stack-frame stays alive in memory even after the outer function exists!
function say667() {
// Local variable that ends up within closure
var num = 42;
var say = function() { console.log(num); }
num++;
return say;
}
var sayNumber = say667();
sayNumber(); // logs 43
Points to remember:
- Whenever you use function inside another function, a closure is used.
- Whenever you use eval() inside a function, a closure is used. The text you eval can reference local variables of the function, and within eval, you can even create new local variables by using eval('var foo = …')
- When you use a new Function(…) (the Function constructor) inside a function, it does not create a closure. (The new function cannot reference the local variables of the outer function.)
- A closure in JavaScript is like keeping a copy of all the local variables, just as they were when a function exited.
- It is probably best to think that a closure is always created just an entry to a function, and the local variables are added to that closure.
- A new set of local variables is kept every time a function with a closure is called (given that the function contains a function declaration inside it, and a reference to that inside function is either returned or an external reference is kept for it in some way).
- Two functions might look like they have the same source text, but have completely different behavior because of their 'hidden' closure. I don't think JavaScript code can actually find out if a function reference has a closure or not.
- If you are trying to do any dynamic source code modifications (for example myFunction = Function(myFunction.toString().replace(/Hello/,'Hola'));), it won't work if myFunction is a closure (of course, you would never even think of doing source code string substitution at runtime, but...).
- It is possible to get function declarations within function declarations within functions… and you can get closures at more than one level.
- I think normally a closure is a term for both the function along with the variables that are captured. Note that I do not use that definition in this article!
- I suspect that closures in JavaScript differ from those normally found in functional languages
No comments:
Post a Comment