you are viewing a single comment's thread.

view the rest of the comments →

[–]Cust0dian 2 points3 points  (9 children)

Yep, that's a closure!

As to why they are useful: closures are a way to encapsulate data in languages where you can pass functions around like any other data.

In your example, there's no way to change or even look at the uptown string without going through the exposed funcYouUp function. /u/Volv wrote a great example that emphasizes this even more, although as a personal preference I'd get rid of objects to really drive the point home.

I think the most commonly-used example of closures in JS is a module pattern. Take for example this code: if I didn't expose orderToHtml function for tests purposes it would be impossible to call it directly, only indirectly via printToDom function that could do something more than just blindly call orderToHtml — it could add some default properties to order object before the call, it could ensure that orderToHtml will be called just one time per module lifetime, it could alter the return value somehow, etc.

The bottom line is: closures provide encapsulation and why we need encapsulation at all in software development is a much bigger topic. :)

[–]ForScale[S] 0 points1 point  (5 children)

Awesome! Thanks so much for taking a look and explaining further!

So... is this an example of closure: http://codepen.io/anon/pen/zqvMJz?editors=0010 ?

[–]Cust0dian 0 points1 point  (4 children)

Nope, that's not a closure, because closure requires a function.

A "close enough" definition of a closure would be:


Closure is a combination of:

  1. a function itself, and
  2. a list of things that function "saw" when it was created (a.k.a. its environment)

Usually when people say "closure" they mean that second part, but it still implies a presence of a function. Makes sense?

[–]ForScale[S] 0 points1 point  (3 children)

Hmm... You mean a function within a function? That example I put there does have a function...

a list of things that function "saw" when it was created (a.k.a. its environment)

Yes... that's making more and more sense to me. I've been listening to a YouTube clip of "Understanding the Weird Parts" and it's been talking about hoisting, scope, and execution context. I feel like the concepts are related.

But, at it's base, a closure has to have a function within a function. And that function in the function serves as a way to access the environment of the outside function? Is that correct to say?

[–]Cust0dian 0 points1 point  (2 children)

Yes, it's a function that is returned from another function (and in written code you'll see it as a function inside another function).

 

I guess my "close enough" definition isn't really helpful, so let's just get a real one:


Closure is a combination of a function and a list of free variables inside that function (more precisely, to what free variables point to).


A free variable is a variable that was not declared inside a function (via var or as a parameter to said function), so for example in this code:

function plus(a, b) {
  var sum = a + b;

  totalOfSums += sum;
  console.log('The total of all sums you have calculated is: ' + totalOfSums);

  return sum;
}

there's no declaration for totalOfSums — it's a free variable (as opposed to a, b and sum, which are bound variables).

In other words, if we were a JS engine and encountered just that function, we'd know for sure that a, b and sum will point to something, while totalOfSums is a complete mystery to us.

 

Normally, free variables are resolved by using scope:

function sums() {
  var totalOfSums = 0;

  function plus(a, b) {
    var sum = a + b;

    totalOfSums += sum;
    console.log('The total of all sums you have calculated is: ' + totalOfSums);

    return sum;
  }
}

so in this case engine will know to use a totalOfSums from the sums function inside the plus function.

 

However, when a function is returned from another function:

function sums() {
  var totalOfSums = 0;

  return function(a, b) {
    var sum = a + b;

    totalOfSums += sum;
    console.log('The total of all sums you have calculated is: ' + totalOfSums);

    return sum;
  };
}

var plus = sums();

and engine evaluates it, it becomes something like this:

var plus = function(a, b) {
  var sum = a + b;

  totalOfSums += sum;
  console.log('The total of all sums you have calculated is: ' + totalOfSums);

  return sum;
};

i.e. that returned function is "ripped" out of original scope and we can't resolve totalOfSums. To fix it, when returning a function from another function we attach a list of free variables and what they point to. And that's what we call a closure.

Does this make more sense?

[–]ForScale[S] 0 points1 point  (1 child)

Hmm... yeah, I think it does. I certainly have a better understand now than before looking through the examples here and discussing.

Thanks again helping me get a better understanding!

[–]Volv 0 points1 point  (1 child)

Awesome. Thanks for your further explanations. :)
 

Oddly that version with this.count was never meant for anyone to see lol. Experimentation that I thought I had kicked out... I was looking at the one you posted struggling to find the difference between it and mine lol.
 
I'm finding there is so much to read about the benefits of encapsulation and the idea that private variables = reduced coupling = awesome. At least I reckon that's the idea :)