Understanding Closure & First class functions

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.

Ok, key idea of closure:

In languages that support closure (which is effectively all now, but used to, until very recently, only be functional[ish] languages like ML and Lisp - eg, Java only got support in 2014 afaik, whereas Lisp had in in late 1960s*), a function has two parts: the code itself, and the values that exist[ed] in the environment it was defined in. When you call a function, it executes the code with any values that exist from where it was defined. That is all that closure is. It is intimately tied to languages that support first-class-functions (ie you can pass functions around as values - they will evaluate to a value, and work the same way, basically because of closure).

So foo/bar/baz examples are almost always not great, but the one here illustrates closure ok:

  1. there is a function, foo.
  2. Inside that is: a variable a, a function which uses variable a, and a call to that function.
  3. No matter where you use that foo function, it’ll carry around that stuff inside. It makes absolutely no difference if you have another variable called a somewhere else, the one inside foo stays the same, it uses the environment where it was defined, not where it was called

* note JS is an attempt to put a version of Lisp (Scheme) into browsers, so is very similar in the way it works - for example first-class functions. It’s just that the syntax was made to look like Java.

1 Like

Apart from what’s been said, I can summarise closures and first class functions as:

  • Closures: It means that inner functions can “capture” the outer scope even after they’ve been executed and returned its value. This property is very important for functional programmers because it allows for things like currying, creating new specialised functions, simulating stateful objects (like counters or entire modules), etc.

  • First class functions: It’s simpler, it just means that functions behave like first class objects, this is:
    a) You can pass them around as arguments and take them as parameters
    b) Have a string representation (not important)
    c) You can return them from functions
    d) You can store them in variables and data structures
    Among other less important but non-ignorable properties.

Sorry guys I think I phrased my question wrong.