0

Firstly, taking note of MDN's definition of a closure:

A closure is the combination of a function and the lexical environment within which that function was declared.

In the below code, a singleton is produced as a result of the IIFE.

var counter = (function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  };   
})();

console.log(counter.value()); // logs 0
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1

It is then said that "those three public functions (increment, decrement, and value) are closures that share the same lexical environment".

In other words, if I interpret that correctly: The following methods/functions: increment, decrement and value, are each, in themselves, closures?

Taking a look at the next code, where there is not an IIFE, but a function factory:

var makeCounter = function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }  
};

var counter1 = makeCounter();
var counter2 = makeCounter();
alert(counter1.value()); /* Alerts 0 */
counter1.increment();
counter1.increment();
alert(counter1.value()); /* Alerts 2 */
counter1.decrement();
alert(counter1.value()); /* Alerts 1 */
alert(counter2.value()); /* Alerts 0 */

"Each of the counters, counter1 and counter2, maintains its independence from the other. Each closure references a different version of the privateCounter variable through its own closure."

Thus, here, is it implying that counter1 and counter2 are each closures? If so, that wouldn't be consistent with the definition provided at the top here of what a 'closure' is?

So in the first code (featuring an IIFE), MDN is saying that each of the inner functions that are being returned are the closures. However, in the 2nd code (featuring a function factory), MDN appears to be saying it is the variables that are referencing the returned object (which contains the 3 methods or function properties: increment, decrement and value), that are closures?

Ultimately, obviously regardless of whether it's an IIFE or a function factory doesn't affect the definition of a 'closure', but the comments made on the page has not allowed me to gain clarity on what actually is the closure(s) here?

Per the MDN definition of a closure above, what I think the closures are:

In the 1st code, the increment, decrement and value functions are each closures that are formed (where all 3 are sharing the same lexical environment - and hence sharing the same closure variable - 'privateCounter').

  • Is there anything inaccurate or incorrect with the above statement?

In the 2nd code, the increment, decrement and value functions are each closures that are formed (where all 3 are sharing the same lexical environment - and hence sharing the same closure variable - 'privateCounter'). BUT, as a result of makeCounter() being called twice, with its return value set to two different variables, there would be two sets of those 3 closures formed (i.e. 6 closures, if you like), each set sharing the same lexical environment (the privateCounter variable).

  • Is there anything inaccurate or incorrect with the above statement?

That's what I understand from the MDN definition, but I have doubts about what the closures actually are in the 2nd code. Surely it's more understandable to say there are only 2 closures in the 2nd code? But in saying that, aren't you implying that the object being returned is a closure, and arguably, objects cannot form or be part of a closure?

tl;dr: What IS(are) the closure(s) in both these two sets of code?

Clarification on this would be great.

151SoBad
  • 115
  • 9
  • *closure is a stack frame which is allocated when a function starts its execution, and not freed after the function returns* . So in **IIFE 1**, `counter` is the closure, while in **IIFE 2**, `counter1` and `counter2` are closures. – gurvinder372 Oct 27 '17 at 14:19
  • I agree. That is a way to think about what the closure is. But how can you relate it contextually to the presented code, if ever asked? That is, can one actually be specific about what the closure actually is in each of the two sets of codes presented above? I am sure there is - hence MDN's attempt at it, but there doesn't appear to be a clear answer there? EDIT: Just noticed your edit. Ok I suspected that as well, but couldn't you argue that those (`counter`, and `counter1 & counter2`) are what _FORM_ the closures, but are not actually the _closures_ themselves? – 151SoBad Oct 27 '17 at 14:21
  • The closure is the combination of the functions, *and* the values and functions available to them (eg privateCounter and changeBy) – TKoL Oct 27 '17 at 14:28
  • I totally agree and understand that, but can the 'closure' formed be contextualised to the code? Or is it an abstract concept, such as that you have described? This is what I think, from @gurvinder372's reply: So it would be correct to say: makeCounter() _forms_ the closure, whereas `counter`, and `counter1 & counter2` _represent_ (because these are the variables that allow you to access/use the "combination of the functions, and the values and functions available to them") the _closures_ themselves? – 151SoBad Oct 27 '17 at 14:31

1 Answers1

1

Your understanding is correct.

Thus, here, is it implying that counter1 and counter2 are each closures?

No. It's referring to their methods. As you said, a closure is always a function.

We could reformulate the sentence as "Each of the counters, counter1 and counter2, maintains its independence from the other. The closures on each object reference a different version of the privateCounter variable through its own closure."

(However, the last word "closure" here doesn't refer to the function, it's just the substantive for the act of closing [over the lexical environment]).

Is there anything inaccurate or incorrect with the above statements?

They're both fine. The only thing I'd mention is that in "sharing the same closure variable - privateCounter" you forgot about the changeBy variable that is in the same scope and shared with it.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Excellent answer - thanks Bergi. Your point in parentheses however, could I confirm that was just to clarify that _each_ closure contained in the object references (`counter1` and `counter2`) are _not_ referencing a different version of the privateCounter variable (because, as we know, each are sharing the same privateCounter variable)? & good point, I have also seen discussions that state closures 'close over' the **variables** in the outer function. But surely it is not just variables, but **functions** as well? Since closures close over the entire outer func's lexical environment, right? – 151SoBad Oct 28 '17 at 05:07
  • I have also seen discussions that mention closures are objects (i.e. "closures are objects that contain a [combination] of the function and a reference to the environment [in which that function was lexically declared]". Can we agree that this is incorrect? That is, I would say, the closure is actually the inner function itself, which implicitly, via [[scope]], has access to its enclosing function's lexical environment (hence why we say that it has access to its enclosing function's variables (and functions, if any). Is this understanding correct? – 151SoBad Oct 28 '17 at 05:13
  • Lastly, back to the question, to confirm and remove any ambiguity, each of the object references (counter1 and counter2), contain 3 closures (increment, decrement, and value), where each object reference's set of 3 closures, are sharing the same closure variables (privateCounter and changeBy)? (EDIT: My first reply/question above was founded on the basis that when you mentioned '_variables_', _function_ names didn't come to mind - perhaps a better term is '_identifier_'? That is, closures close over _identifiers_ (variables AND functions) in its enclosing/outer function's lexical environment?) – 151SoBad Oct 28 '17 at 05:17
  • 1
    1) Yes, the "each" is a bit confusing, but you got it correct 2) function declarations introduce normal variables (that hold a function value) 3) functions are objects anyway in JavaScript (and [all functions are closures](https://stackoverflow.com/a/30252701/1048572)), so closures are `Function` objects that contain both the "code" and the scope reference – Bergi Oct 28 '17 at 08:12
  • Very clear, thanks Bergi. I suspected point 3) but was character-limited so had to omit that part out. Arguably why I mentioned it is because if one blankly said closures are simply objects (with no description as to what this object 'contains'), then arguably one could mistakenly state that there is only _one_ closure in the 2nd code in the OP, that being the _singleton object_ instance (containing the 3 function properties), as a result of the invocation of `makeCounter()`, which `counter1` & `counter2` would now be referencing. This interpretation would be mistaken, and surely not trivial? – 151SoBad Oct 28 '17 at 10:56
  • Another side comment on the link you cited above there. You mentioned in that post that any function that closes over its outer lexical environment (where that environment is empty), can be construed as being an "uninteresting closure". And if so, would that function's scope reference would be `null`, or would it be `undefined`? I suspect `null` - akin to what `Object.prototype`'s prototype (Object.prototype.``__proto__``) references? Or is there no clear-cut answer as this implementation would be browser-dependent? – 151SoBad Oct 28 '17 at 11:09
  • 1
    @151SoBad Dropping scope references when they are not needed is an engine-specific optimisation detail, it's not described in the spec. When talking about functions without free variables, we just call them "functions" instead of "closures". – Bergi Oct 28 '17 at 11:14
  • Noting MDN's definition, "combination of a function ...", is the following statement: "combination of a fn code block" equivalent to the former? Usually when one refers to the 'function', they're referring to the function's code block (its inner scope), and not the function value itself, is that correct? So, because closures are formed before the inner function is actually invoked, can u say it is the "combination of the function _value/definition_.."? Otherwise, if the closure did capture the function's code block, then any PRIVATE vars shouldn't be recreated every call of the inner function. – 151SoBad Oct 28 '17 at 21:25
  • Yes of course the closure closes over the *surrounding* environment, the local variables are created on every call. Regarding the MDN "definition", it was probably inspired by the [Wikipedia one](https://en.wikipedia.org/wiki/Closure_(computer_programming)), where the term "function" refers to the standard generic computer programming meaning of the word - a plain procedure. It does not refer to any JavaScript *value/definition*. – Bergi Oct 28 '17 at 22:48