Thursday, 6 October 2016

javascript - Does a (JS) Closure Require a Function Inside a Function



I'm having a little difficulty with the inherent concept of a closure. I get the basic idea, but here's the thing: I thought that, technically, there "is a closure" inside every Javascript function. To quote wikipedia:





In computer science, a closure (also lexical closure, function closure
or function value) is a function together with a referencing
environment for the nonlocal names (free variables) of that function.
Such a function is said to be "closed over" its free variables.




So since you can define variables inside a function, they are "closed off" to the rest of your code, and so I see that as a closure. Thus, as I understand it:




(function(){var a = 1;}())


Is a (not very useful) example of a closure. Or heck, even just this:



function(){var a = 1;}


But, I think my understanding might be wrong. Others are telling me that for something to be a closure it has to persist a state, and so since nothing persists beyond that code it's not really a closure. That suggests that you need to have:




function(foo){foo.a = 1;}(bar); // bar.a = 1


or even (to ensure un-modifiability):



function(foo){var a = 1; bar.baz = function() { return a}}(bar); // bar.baz() = 1


So, technically speaking (I know several of the examples are practically speaking pointless, but) which of the above examples are actually examples of closures. And does a closure just have to be a space (ie. inside a JS function) where variables can be stored that can't be accessed form outside, or is persistence a key part of a closure's definition?




EDIT



Just noticed the wiki definition for the "closures" tag on :




A closure is a first-class function that refers to (closes over)
variables from the scope in which it was defined. If the closure still
exists after its defining scope ends, the variables it closes over
will continue to exist as well.





While the SO wiki is certainly no final authority, the first sentence does seem to correlate with my understanding of the term. The second sentence then suggests how a closure can be used, but it doesn't seem like a requirement.



EDIT #2



In case it isn't clear from the varying answers here, the wikipedia answer, and the tag answer, there does not seem to be a clear consensus on what the word "closure" even means. So while I appreciate all the answers so far, and they all make sense if you go with the author's definition of closure, what I guess I'm really looking for is ... is there any actual "authoritative" definition of the word (and then if so, how does it apply to all of the above)?


Answer



You're being led astray by a wrong assumption of where the word "closure" comes from.



In a language-theoretic context, the point of a closure is that the function can refer to variables declared outside its own definition. It is immaterial whether it has internal variables, or that the internal variables are not visible from outside. In other words it is about seeing out from the function to its definition environment, not about seeing in from outside the function.




Why the weird word, then? Look at the function in your last example:



bar.baz = function() { return a }


This function contains a mention of the variable a which is not defined in the function body itself. It is a "free" variable of the function body, sort of a "hole" in the definition. We cannot execute the function without knowing, by some extraneous means, what variable the identifier a in the body refers to. Forming a closure at run-time pairs this "open" function body with a reference to the appropriate variable, thereby closing the hole in the definition. And that's where the name comes from.



(If you want the completely technical explanation, the underlying concept is that of a "closed" term in the lambda-calculus, which means one that has no free variables. Only closed term have independent meanings. A closure is then the combination of a (usually compiled) non-closed piece of source code, together with the contextual information that lets it behave like it was a closed term, and therefore be executable).




Addendum: In the common idiom



function() {
var blah;
// some code here
}();


the point is not to get a closure (you will get one, of course, but it doesn't do anything interesting for you), but to create a local scope for the blah variable. A local scope is conceptually quite a different thing from a closure -- in fact most C-lookalikes other than Javascript will create them at every {} block, whereas they may or may not have closures at all.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...