Hi guys, Ive been reading YDKJS and Im on the Scopes & Closures book, Ive been trying to understand closure and first class functions particularly passing them areound, how does this explenation make sense am i on the right track?
//Closure Explenation
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo();
baz(); // 2 -- Whoa, closure was just observed, man.
// function foo(); is executed in the background as soon as it is passed to "var baz" as a value, (var baz = foo(); ).
// Even though var baz references foo() (var baz = foo(); ), when baz(); is called it is not running foo(); at all, what it is doing is going into foo(); and running the bar(); function which was declared inside foo(); and returned by foo();
// So when we run baz(); we can consider that it is the same as running bar(); outside its enclosing scope.
// As we are not running foo(); anymore and it had already executed, run and had returned we would usually assume that the scope of foo(); would be garbage collected like any normal function to free up memory.
// But this does not happen, the scope of foo(); is still saved/retained in memory because the scope of foo(); is still being used by the bar(); function to reference the "var a" every time bar(); it is called.
// This retention/memory of bar is considered a closure. bar(); still has reference to the scope of foo(); and this reference is called a closure.
// Closure lets the function bar(); continue to access the lexical scope (scope of foo(); ) it was defined in at author time.
// how do we know that calling baz(); references bar(); directly and does not run foo(); first? Consider the folowing example:
function foo(b) {
var a = b;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo(b);
baz(3); // ReferenceError: Cant find variable b
// if bar(); was running foo(); first and then running bar(); we could assume that this code would have worked and changed the console.log(); output to "3", because from the looks of it baz(3); has an argument of "3" which we would assume would get passed over to the variable b of foo(b); eventually changing a to b within the function foo(); (var a = b; ).
// but that is not the case as we can see in this error because baz(); does not reference foo(); at all it references bar(); directly and calls it, as if we were calling bar(); from outside the foo(); scope.
// How can we really prove this? Consider the folowing code:
function foo() {
var a = 2;
function bar(b) {
console.log( a + b );
}
return bar;
}
var baz = foo();
baz(3); // 5
// as you can see this time the output is "5" because in the console.log(); of bar(); we had added together "var a" and "var b" (a + b). As "var a" was set to "2" in the scope of foo();, and "var b" was set to "3" when we called baz(3);, we ended up with a result of 5.
// This shows us that baz(); had referenced bar(); directly and calling baz(3); was just like calling bar(3); directly, so the "var b" in bar(b); was directly set to "3" and then through closure bar(); had referenced the scope of foo(); and grabbed the "var a".
// I mention calling baz(); is like calling bar(); directly, some people might ask, why not just call bar(); directly then!?
//Well we cannot call bar(); directly because you cannot call a function from outside of the scope it was declared in. Why? Because function scopes are private, so the only way to call bar(); (or any function) from outside the scope it was declared in is to return it from the function it was declared in and asign it to another variable (in this case baz(); ) which will be called when we want to execute bar(); from outside the acope it was declared in.