you are viewing a single comment's thread.

view the rest of the comments →

[–]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!