A friend of mine and I are currently discussing what is a closure in JS and what isn't. We just want to make sure we really understand it correctly.
Let's take this example. We have a counting loop and want to print the counter variable on the console delayed. Therefore we use setTimeout and closures to capture the value of the counter variable to make sure that it will not print N times the value N.
The wrong solution without closures or anything near to closures would be:
for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
which will of course print 10 times the value of i after the loop, namely 10.
So his attempt was:
for(var i = 0; i < 10; i++) {
(function(){
var i2 = i;
setTimeout(function(){
console.log(i2);
}, 1000)
})();
}
printing 0 to 9 as expected.
I told him that he isn't using a closure to capture i, but he insists that he is. I proved that he doesn't use closures by putting the for loop body within another setTimeout (passing his anonymous function to setTimeout), printing 10 times 10 again. The same applies if I store his function in a var and execute it after the loop, also printing 10 times 10. So my argument is that he doesn't really capture the value of i, making his version not a closure.
My attempt was:
for(var i = 0; i < 10; i++) {
setTimeout((function(i2){
return function() {
console.log(i2);
}
})(i), 1000);
}
So I capture i (named i2 within the closure), but now I return another function and pass this around. In my case, the function passed to setTimeout really captures i.
Now who is using closures and who isn't?
Note that both solutions print 0 to 9 on the console delayed, so they solve the original problem, but we want to understand which of those two solutions uses closures to accomplish this.
Editor's Note: All functions in JavaScript are closures as explained in this post. However we are only interested in identifying a subset of these functions which are interesting from a theoretical point of view. Henceforth any reference to the word closure will refer to this subset of functions unless otherwise stated.
A simple explanation for closures:
Take a function. Let's call it F.
List all the variables of F.
The variables may be of two types:
Local variables (bound variables)
Non-local variables (free variables)
If F has no free variables then it cannot be a closure.
If F has any free variables (which are defined in a parent scope of F) then:
There must be only one parent scope of F to which a free variable is bound.
If F is referenced from outside that parent scope, then it becomes a closure for that free variable.
That free variable is called an upvalue of the closure F.
Now let's use this to figure out who uses closures and who doesn't (for the sake of explanation I have named the functions):
Case 1: Your Friend's Program
for (var i = 0; i < 10; i++) {
(function f() {
var i2 = i;
setTimeout(function g() {
console.log(i2);
}, 1000);
})();
}
In the above program there are two functions: f and g. Let's see if they are closures:
For f:
List the variables:
i2 is a local variable.
i is a free variable.
setTimeout is a free variable.
g is a local variable.
console is a free variable.
Find the parent scope to which each free variable is bound:
i is bound to the global scope.
setTimeout is bound to the global scope.
console is bound to the global scope.
In which scope is the function referenced? The global scope.
Hence i is not closed over by f.
Hence setTimeout is not closed over by f.
Hence console is not closed over by f.
Thus the function f is not a closure.
For g:
List the variables:
console is a free variable.
i2 is a free variable.
Find the parent scope to which each free variable is bound:
console is bound to the global scope.
i2 is bound to the scope of f.
In which scope is the function referenced? The scope of setTimeout.
Hence console is not closed over by g.
Hence i2 is closed over by g.
Thus the function g is a closure for the free variable i2 (which is an upvalue for g) when it's referenced from within setTimeout.
Bad for you: Your friend is using a closure. The inner function is a closure.
Case 2: Your Program
for (var i = 0; i < 10; i++) {
setTimeout((function f(i2) {
return function g() {
console.log(i2);
};
})(i), 1000);
}
In the above program there are two functions: f and g. Let's see if they are closures:
For f:
List the variables:
i2 is a local variable.
g is a local variable.
console is a free variable.
Find the parent scope to which each free variable is bound:
console is bound to the global scope.
In which scope is the function referenced? The global scope.
Hence console is not closed over by f.
Thus the function f is not a closure.
For g:
List the variables:
console is a free variable.
i2 is a free variable.
Find the parent scope to which each free variable is bound:
console is bound to the global scope.
i2 is bound to the scope of f.
In which scope is the function referenced? The scope of setTimeout.
Hence console is not closed over by g.
Hence i2 is closed over by g.
Thus the function g is a closure for the free variable i2 (which is an upvalue for g) when it's referenced from within setTimeout.
Good for you: You are using a closure. The inner function is a closure.
So both you and your friend are using closures. Stop arguing. I hope I cleared the concept of closures and how to identify them for the both of you.
Edit: A simple explanation as to why are all functions closures (credits #Peter):
First let's consider the following program (it's the control):
lexicalScope();
function lexicalScope() {
var message = "This is the control. You should be able to see this message being alerted.";
regularFunction();
function regularFunction() {
alert(eval("message"));
}
}
We know that both lexicalScope and regularFunction aren't closures from the above definition.
When we execute the program we expect message to be alerted because regularFunction is not a closure (i.e. it has access to all the variables in its parent scope - including message).
When we execute the program we observe that message is indeed alerted.
Next let's consider the following program (it's the alternative):
var closureFunction = lexicalScope();
closureFunction();
function lexicalScope() {
var message = "This is the alternative. If you see this message being alerted then in means that every function in JavaScript is a closure.";
return function closureFunction() {
alert(eval("message"));
};
}
We know that only closureFunction is a closure from the above definition.
When we execute the program we expect message not to be alerted because closureFunction is a closure (i.e. it only has access to all its non-local variables at the time the function is created (see this answer) - this does not include message).
When we execute the program we observe that message is actually being alerted.
What do we infer from this?
JavaScript interpreters do not treat closures differently from the way they treat other functions.
Every function carries its scope chain along with it. Closures don't have a separate referencing environment.
A closure is just like every other function. We just call them closures when they are referenced in a scope outside the scope to which they belong because this is an interesting case.
According to the closure definition:
A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).
You are using closure if you define a function which use a variable which is defined outside of the function. (we call the variable a free variable).
They all use closure(even in the 1st example).
In a nutshell Javascript Closures allow a function to access a variable that is declared in a lexical-parent function.
Let's see a more detailed explanation.
To understand closures it is important to understand how JavaScript scopes variables.
Scopes
In JavaScript scopes are defined with functions.
Every function defines a new scope.
Consider the following example;
function f()
{//begin of scope f
var foo='hello'; //foo is declared in scope f
for(var i=0;i<2;i++){//i is declared in scope f
//the for loop is not a function, therefore we are still in scope f
var bar = 'Am I accessible?';//bar is declared in scope f
console.log(foo);
}
console.log(i);
console.log(bar);
}//end of scope f
calling f prints
hello
hello
2
Am I Accessible?
Let's now consider the case we have a function g defined within another function f.
function f()
{//begin of scope f
function g()
{//being of scope g
/*...*/
}//end of scope g
/*...*/
}//end of scope f
We will call f the lexical parent of g.
As explained before we now have 2 scopes; the scope f and the scope g.
But one scope is "within" the other scope, so is the scope of the child function part of the scope of the parent function? What happens with the variables declared in the scope of the parent function; will I be able to access them from the scope of the child function?
That's exactly where closures step in.
Closures
In JavaScript the function g can not only access any variables declared in scope g but also access any variables declared in the scope of the parent function f.
Consider following;
function f()//lexical parent function
{//begin of scope f
var foo='hello'; //foo declared in scope f
function g()
{//being of scope g
var bar='bla'; //bar declared in scope g
console.log(foo);
}//end of scope g
g();
console.log(bar);
}//end of scope f
calling f prints
hello
undefined
Let's look at the line console.log(foo);. At this point we are in scope g and we try to access the variable foo that is declared in scope f. But as stated before we can access any variable declared in a lexical parent function which is the case here; g is the lexical parent of f. Therefore hello is printed.
Let's now look at the line console.log(bar);. At this point we are in scope f and we try to access the variable bar that is declared in scope g. bar is not declared in the current scope and the function g is not the parent of f, therefore bar is undefined
Actually we can also access the variables declared in the scope of a lexical "grand parent" function. Therefore if there would be a function h defined within the function g
function f()
{//begin of scope f
function g()
{//being of scope g
function h()
{//being of scope h
/*...*/
}//end of scope h
/*...*/
}//end of scope g
/*...*/
}//end of scope f
then h would be able to access all the variables declared in the scope of function h, g, and f. This is done with closures. In JavaScript closures allows us to access any variable declared in the lexical parent function, in the lexical grand parent function, in the lexical grand-grand parent function, etc.
This can be seen as a scope chain; scope of current function -> scope of lexical parent function -> scope of lexical grand parent function -> ... until the last parent function that has no lexical parent.
The window object
Actually the chain doesn't stop at the last parent function. There is one more special scope; the global scope. Every variable not declared in a function is considered to be declared in the global scope. The global scope has two specialities;
every variable declared in the global scope is accessible everywhere
the variables declared in the global scope correspond to the properties of the window object.
Therefore there are exactly two ways of declaring a variable foo in the global scope; either by not declaring it in a function or by setting the property foo of the window object.
Both attempts uses closures
Now that you have read a more detailed explanation it may now be apparent that both solutions uses closures.
But to be sure, let's make a proof.
Let's create a new Programming Language; JavaScript-No-Closure.
As the name suggests, JavaScript-No-Closure is identical to JavaScript except it doesn't support Closures.
In other words;
var foo = 'hello';
function f(){console.log(foo)};
f();
//JavaScript-No-Closure prints undefined
//JavaSript prints hello
Alright, let's see what happens with the first solution with JavaScript-No-Closure;
for(var i = 0; i < 10; i++) {
(function(){
var i2 = i;
setTimeout(function(){
console.log(i2); //i2 is undefined in JavaScript-No-Closure
}, 1000)
})();
}
therefore this will print undefined 10 times in JavaScript-No-Closure.
Hence the first solution uses closure.
Let's look at the second solution;
for(var i = 0; i < 10; i++) {
setTimeout((function(i2){
return function() {
console.log(i2); //i2 is undefined in JavaScript-No-Closure
}
})(i), 1000);
}
therefore this will print undefined 10 times in JavaScript-No-Closure.
Both solutions uses closures.
Edit: It is assumed that these 3 code snippets are not defined in the global scope. Otherwise the variables foo and i would be bind to the window object and therefore accessible through the window object in both JavaScript and JavaScript-No-Closure.
I've never been happy with the way anybody explains this.
The key to understanding closures is to understand what JS would be like without closures.
Without closures, this would throw an error
function outerFunc(){
var outerVar = 'an outerFunc var';
return function(){
alert(outerVar);
}
}
outerFunc()(); //returns inner function and fires it
Once outerFunc has returned in an imaginary closure-disabled version of JavaScript, the reference to outerVar would be garbage collected and gone leaving nothing there for the inner func to reference.
Closures are essentially the special rules that kick in and make it possible for those vars to exist when an inner function references an outer function's variables. With closures the vars referenced are maintained even after the outer function is done or 'closed' if that helps you remember the point.
Even with closures, the life cycle of local vars in a function with no inner funcs that reference its locals works the same as it would in a closure-less version. When the function is finished, the locals get garbage collected.
Once you have a reference in an inner func to an outer var, however it's like a doorjamb gets put in the way of garbage collection for those referenced vars.
A perhaps more accurate way to look at closures, is that the inner function basically uses the inner scope as its own scope foudnation.
But the context referenced is in fact, persistent, not like a snapshot. Repeatedly firing a returned inner function that keeps incrementing and logging an outer function's local var will keep alerting higher values.
function outerFunc(){
var incrementMe = 0;
return function(){ incrementMe++; console.log(incrementMe); }
}
var inc = outerFunc();
inc(); //logs 1
inc(); //logs 2
You are both using closures.
I 'm going with the Wikipedia definition here:
In computer science, a closure (also lexical closure or function
closure) is a function or reference to a function together with a
referencing environment—a table storing a reference to each of the
non-local variables (also called free variables) of that function.
A closure—unlike a plain function pointer—allows a function to access
those non-local variables even when invoked outside of its immediate
lexical scope.
Your friend's attempt clearly uses the variable i, which is non-local, by taking its value and making a copy to store into the local i2.
Your own attempt passes i (which at the call site is in scope) to an anonymous function as an argument. This is not a closure so far, but then that function returns another function that references the same i2. Since inside the inner anonymous function i2 is not a local, this creates a closure.
You and your friend both use closures:
A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.
MDN: https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures
In your friend's code function function(){ console.log(i2); } defined inside closure of anonymous function function(){ var i2 = i; ... and can read/write local variable i2.
In your code function function(){ console.log(i2); } defined inside closure of function function(i2){ return ... and can read/write local valuable i2 (declared in this case as a parameter).
In both cases function function(){ console.log(i2); } then passed into setTimeout.
Another equivalent (but with less memory utilization) is:
function fGenerator(i2){
return function(){
console.log(i2);
}
}
for(var i = 0; i < 10; i++) {
setTimeout(fGenerator(i), 1000);
}
Closure
A closure is not a function, and not an expression. It must be seen as a kind of 'snapshot' from the used variables outside the function scope and used inside the function. Grammatically, one should say: 'take the closure of the variables'.
Again, in other words: A closure is a copy of the relevant context of variables on which the function depends on.
Once more (naïf): A closure is having access to variables who are not being passed as parameter.
Bear in mind that these functional concepts strongly depend upon the programming language / environment you use. In JavaScript, the closure depends on lexical scoping (which is true in most C-languages).
So, returning a function is mostly returning an anonymous/unnamed function. When the function access variables, not passed as parameter, and within its (lexical) scope, a closure has been taken.
So, concerning your examples:
// 1
for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); // closure, only when loop finishes within 1000 ms,
}, 1000); // i = 10 for all functions
}
// 2
for(var i = 0; i < 10; i++) {
(function(){
var i2 = i; // closure of i (lexical scope: for-loop)
setTimeout(function(){
console.log(i2); // closure of i2 (lexical scope:outer function)
}, 1000)
})();
}
// 3
for(var i = 0; i < 10; i++) {
setTimeout((function(i2){
return function() {
console.log(i2); // closure of i2 (outer scope)
}
})(i), 1000); // param access i (no closure)
}
All are using closures. Don't confuse the point of execution with closures. If the 'snapshot' of the closures is taken at the wrong moment, the values may be unexpected but certainly a closure is taken!
Let's look at both ways:
(function(){
var i2 = i;
setTimeout(function(){
console.log(i2);
}, 1000)
})();
Declares and immediately executes an anonymous function that runs setTimeout() within its own context. The current value of i is preserved by making a copy into i2 first; it works because of the immediate execution.
setTimeout((function(i2){
return function() {
console.log(i2);
}
})(i), 1000);
Declares an execution context for the inner function whereby the current value of i is preserved into i2; this approach also uses immediate execution to preserve the value.
Important
It should be mentioned that the run semantics are NOT the same between both approaches; your inner function gets passed to setTimeout() whereas his inner function calls setTimeout() itself.
Wrapping both codes inside another setTimeout() doesn't prove that only the second approach uses closures, there's just not the same thing to begin with.
Conclusion
Both methods use closures, so it comes down to personal taste; the second approach is easier to "move" around or generalize.
I wrote this a while ago to remind myself of what a closure is and how it works in JS.
A closure is a function that, when called, uses the scope in which it was declared, not the scope in which it was called. In javaScript, all functions behave like this. Variable values in a scope persist as long as there is a function that still points to them. The exception to the rule is 'this', which refers to the object that the function is inside when it is called.
var z = 1;
function x(){
var z = 2;
y(function(){
alert(z);
});
}
function y(f){
var z = 3;
f();
}
x(); //alerts '2'
After inspecting closely, looks like both of you are using closure.
In your friends case, i is accessed inside anonymous function 1 and i2 is accessed in anonymous function 2 where the console.log is present.
In your case you are accessing i2 inside anonymous function where console.log is present. Add a debugger; statement before console.log and in chrome developer tools under "Scope variables" it will tell under what scope the variable is.
Consider the following.
This creates and recreates a function f that closes on i, but different ones!:
i=100;
f=function(i){return function(){return ++i}}(0);
alert([f,f(),f(),f(),f(),f(),f(),f(),f(),f(),f()].join('\n\n'));
f=function(i){return new Function('return ++i')}(0); /* function declarations ~= expressions! */
alert([f,f(),f(),f(),f(),f(),f(),f(),f(),f(),f()].join('\n\n'));
while the following closes on "a" function "itself"
( themselves! the snippet after this uses a single referent f )
for(var i = 0; i < 10; i++) {
setTimeout( new Function('console.log('+i+')'), 1000 );
}
or to be more explicit:
for(var i = 0; i < 10; i++) {
console.log( f = new Function( 'console.log('+i+')' ) );
setTimeout( f, 1000 );
}
NB. the last definition of f is function(){ console.log(9) } before 0 is printed.
Caveat! The closure concept can be a coercive distraction from the essence of elementary programming:
for(var i = 0; i < 10; i++) { setTimeout( 'console.log('+i+')', 1000 ); }
x-refs.:
How do JavaScript closures work?
Javascript Closures Explanation
Does a (JS) Closure Require a Function Inside a Function
How to understand closures in Javascript?
Javascript local and global variable confusion
I would like to share my example and an explanation about closures. I made a python example, and two figures to demonstrate stack states.
def maker(a, b, n):
margin_top = 2
padding = 4
def message(msg):
print('\n’ * margin_top, a * n,
' ‘ * padding, msg, ' ‘ * padding, b * n)
return message
f = maker('*', '#', 5)
g = maker('', '♥’, 3)
…
f('hello')
g(‘good bye!')
The output of this code would be as follows:
***** hello #####
good bye! ♥♥♥
Here are two figures to show stacks and the closure attached to the function object.
when the function is returned from maker
when the function is called later
When the function is called through a parameter or a nonlocal variable, the code needs local variable bindings such as margin_top, padding as well as a, b, n. In order to ensure the function code to work, the stack frame of the maker function which was gone away long ago should be accessible, which is backed up in the closure we can find along with the function message object.
Related
I am learning closure and have basic doubt.
function makeCounter() {
let count = 0;
return function() {
return count++;
};
}
let counter = makeCounter();
Here when we are returning function it has closure with outer scope. so it has a closure with count.
var x = 1;
function func() {
console.log(x); // does func has closure with x ??
}
func();
So my question is , only nested function makes closure ??
or top level func has also closure with x ??
Closures in JavaScript are implemented using the [[OuterEnv]] internal field of the [[EnvironmentRecord]] internal field of function declarations. The [[OuterEnv]] value is then copied to the execution context created any time a function is called. This value is then used to create the scope chain, enabling the closure behavior.
Functions declared in the global context are no different in this regard and maintain a link to their surrounding environment, the Global Environment Record.
In the global context, variables declared using var and function declarations behave subtly differently to those declared inside other functions, in that they end up as properties on the global object, but this is an implementation detail.
For the sake of conversation, lets say that every closure creates a "scope" where variables are defined - everything within the closure/scope can access variables, anything outside cannot. With that said, there are two different types of implied closures you should be aware of.
This is not an exhastive description of how closures work, but more of description of the basic practical concepts as they relate to this question. There is much more going on with how call stacks are created, lexical scoping, "global" scope within NodeJS, iframes, sandboxing, var vs const/let, block vs function scopes, and other concepts which I will leave to the reader to discover on their own.
The browser/window/global scope
In the browser, you have the top-level scope (basically window, often referred to as the "global" scope). This kind of acts as a closure in that all "non-enclosed" variables are defined as part of the window scope and are available to most other code running on that page. For example, if you include the following script in the browser, x is part of the global/window scope, whereas y and z are enclosed inside their own nested scopes.
// basic-script.js
// x becomes part of the global/window scope
const x = 10;
(() => {
// y is enclosed in a separate, nested closure
const y = 20;
// x is available in this nested scope/closure
console.log('The sum of x and y is', x + y);
function foo() {
// z is enclosed in a separate, nested closure
const z = 5;
// x and y are both available in this nested scope/closure
console.log('The sum of x y and z is', x + y + z);
}
foo();
// z is not available to the parent scope
console.log(z); //-> undefined
})();
// y is not available to the parent scope
console.log(y); //-> undefined
<script src="basic-script.js"></script>
<script>
// this works because x is not enclosed
console.log('The value of x is', x);
// y and z are not available as they are inside a separate closure
console.log(y, z); //-> undefined, undefined
</script>
JavaScript modules
When you write JavaScript which is imported or required by other modules, every module is automatically wrapped in its own closure. For example, if you were to import/require the above basic-script.js into another JavaScript file, the above would be automatically enclosed like this:
(function() {
var x = 10;
// ... other code removed for brevity
})();
There is some other magic going on for exposing exports and so forth, but that's beyond the scope of this answer (pun intended). If JS modules were not wrapped in their own closure, then you would have a mess of naming collisions and reference issues, as well as a security nightmare.
So to answer your question, yes - your second example shares a closure with "x" - the closure is implicitly created depending on your environment.
Don't know, if you are still searching for the answer or not.
What is you meant by top level, I think you are talking about the global scope. To understand closure one should understand scope better.
And No, Closure in not work in global scope. The main reason of closure is to create a function that return a function with specific variables/calculations with it so that you can reuse that value again. I have a detailed blog in scope, closure and lexical environment. You can check it out https://shimulhsn.hashnode.dev/lexical-environment-and-scope-chain
A practical use of closures is creating a "scope" of protection around variables and functions declared within that function from outside interference. The top scope is "global", accessed using the window variable (an object). Everything, regardless what scope it was declared in, has access to it.
A function declared in global scope creates its own scope that no expression in the global scope and other "sub-global" scopes has access to. Functions declared in the global scope or declared inside other functions create their own scope, that even its immediate parent scope doesn't have access to.
Any variable declared—var, let, const—inside a function block is accessible in that function scope and any sub-scope created within that function scope—i.e., nothing outside that function scope can access it, (except a mechanism the function creating the scope may provide).
The second example in the question, where x is declared in the global scope, means everything has access to x. If x is later changed it is changed in all scopes. x is wide-open to interference anywhere in the code.
var x = 1; <-- declared outside func()
function func() {
// ...etc., etc., etc.
In the first example:
function makeCounter() {
let count = 0;
return function() {
return count++;
};
}
...makeCounter() creates a scope that includes count and an anonymous function, and that has access to them. Sub-scopes within this scope also have access to them. However, any expression in the global scope or other sub-global scopes do not have access to them.
Regarding the description that closures give access to an outer function's scope from an inner function—that scope access travels "up", accessing every parent scope, all the way to global scope, regardless how far "down" the "scope-chain" it goes. For example:
const can_i_reach_global = 'yes';
topLevel();
function topLevel () {
console.log('topLevel func, can_i_reach_global:', can_i_reach_global);
oneDeep();
function oneDeep () {
console.log('oneDeep func, can_i_reach_global:', can_i_reach_global);
twoDeep();
function twoDeep () {
console.log('twoDeep func, can_i_reach_global:', can_i_reach_global)
}
}
}
So, as far as practical definitions go, simply stating function closure "...gives you access to an outer function's scope from an inner function..." doesn't describe the usefulness of this programming construct.
In the below code snippet, i is declared after function f, so how can function f access i's value?
let f;
if (true) {
f = () => {
console.log(i)
}
let i = 1;
}
f();
i is declared after function f
Ehm, yes, but in the same scope (block).
i is declared in the same block as the value of f (an anonymous function that uses i), so it is in scope:
f = () => {
console.log(i)
}
// same scope as the definition of the anonymous function:
let i = 1;
Now at the time of declaration, the anonymous function does not need to know what i is, and if you never declared it, it would just resolve to undefined when you do f().
At the time of execution, i is already declared and assigned a value. The anonymous function "recalls" this variable because it was declared in it's scope. This is called a closure.
let keyword scope.
First of the let keyword scope for block of code in your program 'i' is inside of if block so 'i' value scope is inside of if block.
so,if you create 'n' number of function inside of if block it'll access the 'i' value.
please check my example remove the comment in f1() inside console.log(j) and put debugger you'll understand clear.
Here, you'll get error because 'j' is only access for f() means 'j' scope only inside of f(). If you use inside of f() it'll access. Check f2() it's able to access 'j' value.
<script>
debugger
let f,f1,f2;
if (true) {
f = () => {
console.log(i)
let j=11;
f2=()=>{
console.log(j);
}
}
f1=()=>{
console.log(i);
//console.log(j);
}
let i = 1;
}
f();
f1();
f2();
</script>
You are correct that the variables declared by lexical let declarations may not be accessed without error until after the declaration lexically occurs. (This is in contrast to var declarations, which make their declared variable accessible and referencible starting from the top of their containing scope, regardless of where the declaration occurs within that scope.)
The variables referenced by name in f are not accessed until f is actually called. The JavaScript engine does not ask the question "In what scope is the variable i and what is its value?" until f is executed. At the chronological time f actually is executed, the surrounding block scope has had the variable i made accessible within it, so f can use that variable to resolve the identifier i.
When you refer to i at execution time, the JavaScript engine looks up the scope chain to find the nearest declared variable named i. The declaration let i is an instruction to the JavaScript engine to make available a variable named i to the current block scope. The fact that the surrounding scope has no accessibl i at the time f is defined is immaterial; what matters is that the scope does have a variable i by the time f is executed.
Consider this example:
var f;
if(true) {
f = ()=>{ console.log(i) }
try { f(); } catch(e) { console.log(e); }
let i = 1;
try { f(); } catch(e) { console.log(e);}
}
The first call produces an error, because during the execution of f, no i has yet been made accessible, while the second execution, after the let i statement, runs without error.
As Javascript is an interpreted language, it will execute statements one at a time, line by line, without looking at the entire code first (unlike compiled languages). What this means is that your function will not throw an error at the line console.log(i); before runtime.
At runtime, you are defining and initializing i before calling the function f, so by the time f is called, the value of i is already known.
Regarding scopes, i and f are declared in the same block (not inside a function or anything), therefore f can access i fine. No scope issues there.
// Code Starts
var a = 10;
function outer() {
function inner() {
console.log(a);
console.log(b);
};
var b = 20;
return inner;
}
var innerFn = outer();
innerFn();
// Code Ends
My Question is:
In Closures, the function remembers the scope information from the time the function object is created (In the above case, in the compilation phase) but at that time the assignments (for a and b) haven't really happened. So, how are the values for variables a and b retained.
Please correct me if something is wrong in the above statement.
As you said in your first sentence, the closure remembers the scope information. That includes the references to the variables, which already will have been declared (or are declared at the same time as the function). It does not matter what values these variables have - they are evaluated when the variables are actually used when the closure is called.
You will notice that when you overwrite a after having created the closure in the outer() call, it will give you the new value of a when calling innerFn(). Closures do not remember the values from the time of their creation.
I believe the closure in this case is actually created when you return inner, not when you define the function inner. Until you create a reference to a function, the closure mechanism would have no meaning.
Hey i came across this video on youtube http://www.youtube.com/watch?v=KRm-h6vcpxs
which basically explains IIFEs and closures. But what I am not understanding is whether i need to return a function in order to call it a closure.
E.x.
function a() {
var i = 10;
function b() {
alert(i);
}
}
in this case can i call it a closure as it is accessing the 'i' variable from the outer function's scope or do i need to return the function like this
return function b(){alert(i);}
A closure is simply a function which holds its lexical environment and doesn't let it go until it itself dies.
Think of a closure as Uncle Scrooge:
Uncle Scrooge is a miser. He will never let go of his money.
Similarly a closure is also a miser. It will not let go of its variables until it dies itself.
For example:
function getCounter() {
var count = 0;
return function counter() {
return ++count;
};
}
var counter = getCounter();
See that function counter? The one returned by the getCounter function? That function is a miser. It will not let go of the count variable even though the count variable belongs to the getCounter function call and that function call has ended. Hence we call counter a closure.
See every function call may create variables. For example a call to the getCounter function creates a variable count. Now this variable count usually dies when the getCounter function ends.
However the counter function (which can access the count variable) doesn't allow it to die when the call to getCounter ends. This is because the counter function needs count. Hence it will only allow count to die after it dies itself.
Now the really interesting thing to notice here is that counter is born inside the call to getCounter. Hence even counter should die when the call to getCounter ends - but it doesn't. It lives on even after the call to getCounter ends because it escapes the scope (lifetime) of getCounter.
There are many ways in which counter can escape the scope of getCounter. The most common way is for getCounter to simply return counter. However there are many more ways. For example:
var counter;
function setCounter() {
var count = 0;
counter = function counter() {
return ++count;
};
}
setCounter();
Here the sister function of getCounter (which is aptly called setCounter) assigns a new counter function to the global counter variable. Hence the inner counter function escapes the scope of setCounter to become a closure.
Actually in JavaScript every function is a closure. However we don't realize this until we deal with functions which escape the scope of a parent function and keep some variable belonging to the parent function alive even after the call to the parent function ends.
For more information read this answer: https://stackoverflow.com/a/12931785/783743
Returning the function changes nothing, what's important is creating it and calling it. That makes the closure, that is a link from the internal function to the scope where it was created (you can see it, in practice, as a pointer. It has the same effect of preventing the garbaging of the outer scope, for example).
By definition of closure, the link from the function to its containing scope is enough. So basically creating the function makes it a closure, since that is where the link is created in JavaScript :-)
Yet, for utilizing this feature we do call the function from a different scope than what it was defined in - that's what the term "use a closure" in practise refers to. This can both be a lower or a higher scope - and the function does not necessarily need to be returned from the function where it was defined in.
Some examples:
var x = null;
function a() {
var i = "from a";
function b() {
alert(i); // reference to variable from a's scope
}
function c() {
var i = "c";
// use from lower scope
b(); // "from a" - not "c"
}
c();
// export by argument passing
[0].forEach(b); // "from a";
// export by assigning to variable in higher scope
x = b;
// export by returning
return b;
}
var y = a();
x(); // "from a"
y(); // "from a"
The actual closure is a container for variables, so that a function can use variables from the scope where it is created.
Returning a function is one way of using it in a different scope from where it is created, but a more common use is when it's a callback from an asynchronous call.
Any situation where a function uses variables from one scope, and the function is used in a different scope uses a closure. Example:
var globalF; // a global variable
function x() { // just to have a local scope
var local; // a local variable in the scope
var f = function(){
alert(local); // use the variable from the scope
};
globalF = f; // copy a reference to the function to the global variable
}
x(); // create the function
globalF(); // call the function
(This is only a demonstration of a closure, having a function set a global variable which is then used is not a good way to write actual code.)
a collection of explanations of closure below. to me, the one from "tiger book" satisfies me most...metaphoric ones also help a lot, but only after encounterred this one...
closure: in set theory, a closure is a (smallest) set, on which some operations yields results also belongs to the set, so it's sort of "smallest closed society under certain operations".
a) sicp: in abstract algebra, where a set of elements is said to be closed under an operation if applying the operation to elements in the set produces an element that is again an element of the set. The Lisp community also (unfortunately) uses the word "closure" to describe a totally unrelated concept: a closure is an implementation technique for representing procedures with free variables.
b) wiki: a closure is a first class function which captures the lexical bindings of free variables in its defining environment. Once it has captured the lexical bindings the function becomes a closure because it "closes over" those variables.”
c) tiger book: a data structure on heap (instead of on stack) that contains both function pointer (MC) and environment pointer (EP), representing a function variable;
d) on lisp: a combination of a function and a set of variable bindings is called a closure; closures are functions with local state;
e) google i/o video: similar to a instance of a class, in which the data (instance obj) encapsulates code (vtab), where in case of closure, the code (function variable) encapsulates data.
f) the encapsulated data is private to the function variable, implying closure can be used for data hiding.
g) closure in non-functional programming languages: callback with cookie in C is a similar construct, also the glib "closure": a glib closure is a data structure encapsulating similar things: a signal callback pointer, a cookie the private data, and a destructor of the closure (as there is no GC in C).
h) tiger book: "higher-order function" and "nested function scope" together require a solution to the case that a dad function returns a kid function which refers to variables in the scope of its dad implying that even dad returns the variables in its scope cannot be "popup" from the stack...the solution is to allocate closures in heap.
i) Greg Michaelson ($10.15): (in lisp implementation), closure is a way to identify the relationship betw free variables and lexical bound variables, when it's necessary (as often needed) to return a function value with free variables frozen to values from the defining scope.
j) histroy and etymology: Peter J. Landin defined the term closure in 1964 as having an environment part and a control part as used by his SECD machine for evaluating expressions. Joel Moses credits Landin with introducing the term closure to refer to a lambda expression whose open bindings (free variables) have been closed by (or bound in) the lexical environment, resulting in a closed expression, or closure. This usage was subsequently adopted by Sussman and Steele when they defined Scheme in 1975, and became widespread.
My question is really more about scope in JavaScript, rather then closures.
Let's take the following code:
var f = function () {
var n = 0;
return function () {
return n++;
};
}();
console.log(f());
console.log(f());
The above code outputs:
0
1
As you can see from the above code, f (self-invoked) returns a function, creating a closure of n.
So, it works with an anonymous function; thus, I then tried it with a named function:
var f2 = function () {
return n++;
};
var f = function () {
var n = 0;
return f2;
}();
console.log(f2()); // <= [n is not defined]
The above code doesn't work, with the error n is not defined. I assume that this is a scoping issue; but I cannot figure why exactly;
Why is it that the scope is the same with an anonymous, inner function but does not work with a named, outer function?
Also, in the second example, am I creating a closure?
The closure is created in the first example because the code in the anonymous function uses a local variable that is declared outside of the anonymous function.
In the second example the scope of the n variable in the function f2 is already decided when the function is declared. Creating a local variable with the same name doesn't change the meaning of the function, and using the function inside another function doesn't change it's scope. Thus, the function doesn't use the local variable.
scoping in javascript is lexical http://en.wikipedia.org/wiki/Scope_%28programming%29#Static_scoping_.28also_known_as_lexical_scoping.29
There is no way for f2 to figure out where it should take variable n.
In first example anonymous function is inside function f, in second - outside (f2 instead of anonymous). So, f2 cannot access variable n, because it is in another scope and inaccessible (invisible). Try put f2 declaration inside f.
In your second example, you are not creating a closure, you are simply returning a global variable. f2 is not being closed over because it was declared in a more general (in this case, global) scope, and n is declared in a more specific scope. Closure is possible down the scope chain "funnel," not up, and is only effective when all related entities are defined in the same scope.
We could rewrite your second example to make it work with a named function:
var f = function() {
var n = 0;
var f2 = function() {
return n++;
};
return f2;
}();
console.log(f());
console.log(f());
This would output, 0 and 1 as your first example did.
As the other answers have stated, its not about the function being named or anonymous, its about scope of n and f2. Since you declared f2 outside of f in your example, it had no access to the variable n declared inside the scope of f.