Hacker News new | past | comments | ask | show | jobs | submit login
JavaScript closures vs. anonymous functions (stackoverflow.com)
57 points by hammerha on March 18, 2013 | hide | past | favorite | 18 comments



Wow, that was needlessly complicated and (IMO) incorrect.

Any function that has free variables that are not global variables is a closure. Another way to think about it: any function that cannot be implemented in C is a closure.

So, in these examples, the inner functions are closures, the outer ones are not, but only because the outer ones are used in a global scope. If you enclosed everything in another function, then also the outer functions would be closures.


> free variables that are not global variables

These are named "upvalues" in Lua parlance (even though they are read/write, the "value" part is a leftover of a previous Lua version where these variables were read-only and frozen from the closure viewpoint).

It really simplifies the discourse...

Are there other short names for them in other languages? I don't know of any.

> So, in these examples, the inner functions are closures, the outer ones are not, but only because the outer ones are used in a global scope. If you enclosed everything in another function, then also the outer functions would be closures.

This is probably nitpicking, but in the examples on Stack Overflow, the outer functions don't close over locals of the parent scope. Their closure is thus empty, and I don't call these functions closures. Not sure if it is correct, though.


Hm... let me be more explicit:

  for(var i = 0; i < 10; i++) {
      setTimeout(function f() {
          console.log(i);
      }, 1000);
  }
Here, technically speaking, `f` is not a closure, since it doesn't close over any local variables, since there are none (`i` is global).

  function a() {
    for(var i = 0; i < 10; i++) {
        setTimeout(function f() {
            console.log(i);
        }, 1000);
    }
  }
Now, `f` is a closure, since it closes over the variable `i`, which is local to `a`. Note, however, that `f` closes over the variable, not over its value. That is the reason that I prefer to call such variables (heap-allocated) boxes, not upvalues.


You appear to be using a pretty non-standard definition of "closure". Generally speaking (AFAIK), a closure is the function and its referencing environment (with the env potentially simplified to only those variables which occur free in the function). In both your examples `i` occurs free, so it would be part of the closure. Since `i` is global(ish) I guess an interpreter could potentially skip placing it in the closure as an optimization, but I'm not seeing any value to not considering it as part of the closure from a language-understanding standpoint.

As an aside...both of your examples have the same effect: logging "10" 10 times. Did you mean something like

  for(var i = 0; i < 10; i++) {
    (function (_i) {
      setTimeout(function f() {
        console.log(_i);
      }, 1000);
    })(i);
  }
instead?


I decided to exclude global variables from my definition of closure to make it perfectly clear that closure, as it exists in JavaScript, LISP, Python and most other functional/modern languages, is different from raw function that can be defined in C, Java, and similar.

No, I deliberately chose the "wrong" example, and included a Note, saying that the function doesn't close over the values of its free variables, but rather over the whole variables (in different words, over the references to the values).


The historical Lisp term is "upwards funargs".


Correct - no idea why people get confused.

Closures are when you want "This this in that" and vanilla anonymous functions when you want "That this in that" ;)


Your response might be technically correct, but it's not really what the reader was asking or what is interesting to ask. Not to mention that the winning answer addresses that in the very top of his reply.


Chapter 3 in "Structure and Interpretation of Computer Programs" (SICP) explains the environment model to evaluate scheme. That's exactly what you need to understand javascript closures.

Only read the 3.2 part, it's not long: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-21.html...


This question comes up so often both in IRC support channels and on SO that I don't understand why this wasn't closed as a duplicate.

The accepted answer also overcomplicates what could be a very simple answer.

In a quick Google, I found this. Asked in '08, not '12: http://stackoverflow.com/questions/111102/how-do-javascript-...


The second answer states it best: "They all use closure(even in the 1st example)."

If you're accessing a local variable from a different function scope than it was created in then you are using a closure - there is nothing special about how it was defined, this is the only distinction.


What are the applications of this distinction?


They are completely orthogonal. Javascript, Lua, Scheme and others implement

* first class functions,

* anonymous functions, and

* closures (via lexical scope),

but some languages only implement some of these features (Python, for example has limited support for anonymous functions, and Emacs Lisp used to have the first two, but not the last one).

So, in Javascript:

    function outer() {
      var closed_over_local = "Hey ya!"; // The variable must be a local in the parent scope.

      function inner() {
        alert(closed_over_local);
      }

      return inner;
    }

    foo = outer(); 
    foo(); // Alerts "Hey ya".
Here you can see a named function that is a closure, since it closes over a local of the parent scope.

On the other hand, you can have an anonymous function that's either pure, no outer references:

    [1,2,3].map(function(i) { return i*2; });
... or an anonymous function that only references globals. AFAIK, these are not closures (they don't close over variables of the parent scope).


Emacs lisp has dynamic scoping which allows functions to modify the variables in a caller's scope, which is horrific.


Emacs Lisp has now lexical scope.

Recent Changes:

* Lisp Changes in Emacs 24.1

Code can now use lexical scoping by default instead of dynamic scoping. The `lexical-binding' variable enables lexical scoping for local variables. It is typically set via a file-local variable in the first line of the file, in which case it applies to all the code in that file.


Closures and plain anonymous functions solve different problems. Using one when you wanted the other is a good way to cause problems you don't how to solve if you don't know the difference.

The SO thread has some good examples. A common one is using some closed-over value like it lives inside the function's scope and not the parent scope that's shared between the closures, which is wrong if you return another copy of the function and expect a different copy of that value.

  var problems = [];
  function ProblemFactory() {
    this.causeProblem = function(name) {
      problems.push(name);
    };
  }

  new ProblemFactory().causeProblem('isolation');
  new ProblemFactory().causeProblem('failure');
  problems.length === 2; // true
Edits: clarity, example code.


A little clearer, consider this example:

    function sumArray(arr){
        return arr.reduce(function(accumulator, value){
            return accumulator + value;
        }, 0);
    }
The inner function here is what we typically refer to as an anonymous function. However, closures can also be anonymous:

    function sumArray(arr){
        var sum = 0;
        arr.forEach(function(value){
            sum += value;
        });
        return sum;
    }
Both of these do the same thing. One is a closure, the other isn't. The only difference is that the closure has a free variable.

The answer, in this SO link, says that the function 'f' is not a closure in the first example which isn't accurate. Consider the canonical wrong way to do it:

    for (var i = 0; i < 10; i++){
        setTimeout(function(){
            console.log(i);
        }, 100);
    }
This function here (or rather functions) is anonymous and it is also closed over i because it is external to the function. It doesn't matter that i is global, because this code would behave the same if it were presented in global scope or inside a function somewhere. The fact that you get 10 10s printed is because the variable is manipulated by the loop and every closed function created is closed over the same variable. This answer argues awkwardly that free variables that are global don't count towards being closures.


I'm not sure what your point is. If no line ever told me what a closure was, it'd still be quite clear that problems should have length 2.

Could you show an example where making the distinction is not obvious/intuitive and could cause problems?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: