What are closures?

JScript, as I noted yesterday, is a functional language. That doesn’t mean that it works particularly well (though I hope it does) but rather that it treats functions as first-class objects. Functions can be passed around and assigned to variables just as strings or integers can be.

A reader commented yesterday that “closures are your friends”. Well, actually there are important situations where closures are NOT your friends! Let’s talk a bit about those. First off, what’s a closure?

Consider the following (contrived and silly, but pedagocially clear) code:

function AddFive(x) {
  return x + 5;

function AddTen(x) {
  return x + 10;

var MyFunc;
if (whatever)
  MyFunc = AddFive;
  MyFunc = AddTen;
print(MyFunc(123)); // Either 133 or 128.

Here we have a typical functional scenario. We’re deciding which function to call based on some runtime test. Now, one could imagine that you’d want to generalize this notion of an “adder function”, and you would not want to have to write dozens and dozens of adders. What we can do is create an adder factory:

function AdderFactory(y) {
  return function(x){return x + y;}

var MyFunc;
if (whatever)
  MyFunc = AdderFactory(5);
  MyFunc = AdderFactory(10);
print(MyFunc(123)); // Either 133 or 128.

The anonymous inner function remembers what the value of y was when it was returned, even though y has gone away by the time the inner function is called! We say that the inner function is closed over the containing scope, or for short, that the inner function is a closure.

This is an extremely powerful functional language feature, but it is important to not misuse it. There are ways to cause memory-leak-like situations using closures. Here’s an example:

<div class=’menu-bar’ id=’myMenu’></div>
<script language=’javascript’>
var menu = document.getElementById(‘myMenu’);
function AttachEvent(element) {
  element.attachEvent( “onmouseover”, mouseHandler);
  function mouseHandler(){ /* whatever */ }

Someone has, for whatever reason, nested the handler inside the attacher. This means that the handler is closed over the scope of the caller; the handler keeps around a reference to element which is equal to menu, which is that div. But the div has a reference to the handler.

That’s a circular reference.

Now, the JScript garbage collector is a mark-and-sweep GC so you’d think that it would be immune to circular references. But the IE div isn’t a JScript object; it is not in the JScript GC, so the circular reference between the div and the handler will not be broken until the browser completely tears down the div.

Which never happens.

This page used to say that IE tears down the div when the page is navigated away, but it turns out that that’s not right.  Though IE did briefly do that, the application compatibility lab discovered that there were actually web pages that broke when those semantics were implemented.  (No, I don’t know the details.) The IE team considers breaking existing web pages that used to work to be way, way worse than leaking a little memory here and there, so they’ve decided to take the hit and leak the memory in this case.

Don’t use closures unless you really need closure semantics. In most cases, non-nested functions are the right way to go.

Comments (23)

  1. Blake says:

    For the record, the ‘closures are you friend’ comment was meant to be humor and not a blanket recommendation.

    One unexpected place I have found JScript’s closures particularly useful is in breaking up long calculations that have a lot of state on the stack. You can’t pump messages manually in the browser but you can window.setTimeout(function() { /* next block of code */ }, 0) which permits you progress bar to repaint. No memory is leaked in this scenario.

    Obviously this is not the sort of use of closures one sees in a more traditionally functional language, but it solves an otherwise intractable problem.

  2. Adrian says:

    I’m confused… I thought that the definition of "functional programming" was that everything is accomplished by application of functions to existing values, thus producing new values — the most obvious feature of such a language being the lack of "destructive" operators. The definition at the "Functional Programming FAQ" (see http://www.cs.nott.ac.uk/~gmh//faq.html#functional-languages) seems to agree.

    But Eric defines a functional language as one that has functions as first-class objects. This seems like a totally different issue. In fact, it seems like first-class functions aren’t too rare in languages that wouldn’t usually be considered "functional."

    Am I missing something?

  3. Eric Lippert says:

    Look at it this way: functional programming is as you define it. A "functional language" is a language in which one can do functional programming.

    Therefore JScript is a functional language. It is also a procedural language and an object oriented language, as it supports those programming styles as well.

    The fact that JScript allows you to do non-functional programming doesn’t, by the definition above, make it not a functional language. After all, you can write non-pure-functional programs in Scheme too.

    Does that make more sense?

  4. elias says:

    It is not clear what to call functional programming.
    Scheme may be considered an imperative language, because it allows assignment and other imperative features like i/o "functions". On the other hand languages like Miranda, or Haskell are pure functional languages, because of the lack of states (introduced by assignment, and imperative procedures) semantics is clear. More over those languages are lazy, it means they do not perform a computation if it is not needed, it is an advantage see the next pseudocode

    f(x,y) = if x > 5 then x else y
    g(x,y) = f(x,x/y)
    h = g(10,0)

    What is the value of h? 10 of course, try this in Scheme or Java or any eager (non lazy) language, and you get a division by 0 error exception (another imperative feature) the reason is that 10/0 is never computed in a lazy language, the if-then-else function is lazy in many languages (test?thenpart:elsepart in C).

    Other important feature in functional languages is that you can build programs just by function composition.
    Not by applications, it is you do not need variables.

    h = filter (>5) . map (^2)
    h [1..10]

    [1..10] is the list [1,2,3,4,5,6,7,8,9,10]
    may be defined (in a lisp style) as
    filter test list = if (null list) then [ ]
    else if test (hd list)
    then (hd list):filter test (tl list)
    else filter test (tl list)
    but functional languages allow pattern matching in definitions it is shorter and more clear
    filter test [ ] = [ ]
    filter test (x : xs) = if (test x) then x : filter test xs
    else test xs
    just write a case for every constructor (for lists [], and : (cons) ). and map is defined by:
    map f [ ] = [ ]
    map f (x : xs) = f x : map f xs

    (>5) in Lisp/Scheme you would write (lambda (x)(> x 5))
    and (lambda(x)(^ x 2)) instead of (^2), you may have noticed the absence of parethesis in function arguments
    map f list instead of map (f, list) the reason is that functions are in curried form (curried in honor of Haskell Brooks Curry, founder of combinatory logic) it means they take one argument at a time, for that reason
    (1 +) denotes a function expecting a number calculating its sucessor.

    the dot is functional composition you use it in mathematics.

    ( f . g ) x = f ( g x )

    it is possible, but not practical, to never use variables, more over you can build every function with just 2 elementary funtions S and K
    defined as follows K x y = x and S x y z = x y ( x z )
    combining SKK you get I the identity function I x = x
    this is of theoretical interest, but also practical interest,
    Erik said "closures are your friends", well one may say
    "thunks are your friends" instead, thunks are closure like structures used to implement lazy evaluation, the other way to imlement it is by transforming the funtion into elementary functions or combinators SKI would be enough but David Turner (also the author of Miranda)
    developed a better set known as Turner’s combinators.

    I can’t see the lenght of this comment, but I think it is large enough, so my conclusion:

    Higher Order Functions in Java/JavaScript is a good thing. Although they use closures not thunks, but is ok for a non lazy language. The lack of lists in imperative languages (you can define your data type i know) may limit its use because problems with stack overflow due to parameter passing semantics on those languages and the lack of efficient garbage collector.
    The lack of curried functions (although you may define a curried version with higher order functions) do not encourage to think programs as function composition, it encourage the applicative style (Scheme has the same limitant (I am a radical pure functional programer)).

    You want to write functional programs, then it would be better to embed a functional language in browsers, otherwise the patch to imperative laguages wont be easy to use. However is a nice feature to have higher order functions, no doubt. But not enough.

  5. Dan Shappir says:

    Given the content of this discussion,I think it’s appropriate to mention the BeyondJS JavaScript library developed by Sjoerd Visscher and myself. You can find it at http://w3future.com/html/beyondJS/ (a slightly dated version, I will upload a newer version any day now).

    Not your standard run-of-the-mill JavaScript library, BeyondJS targets the JavaScript language itself. Building on JavaScript’s intrinsic functional capabilities it adds loads of features that transform it into a truly functional programming language. Not a pure functional language but a functional language non-the-less.

    Here are some of the features BeyondJS provides:
    1. currying
    2. functional composition
    3. list comprehensions
    4. lazy lists (lists whose members are lazy evaluated)
    5. streams
    a lots more.

    For example, lets implement the example provided by elias using JavaScript with BeyondJS:


    Actually, (1).to(10) computes the JavaScript Array [1,2,3,4,5,6,7,8,9,10]. If you want a lazy list you would use (1).lazy(10) instead.

    Speaking of lazy lists, BeyondJS even supports recursive list definitions. Consider this Haskell definition Fibonacci sequence:

    fibs = 0 : 1 : (zipWith (+) fibs (tail fibs))

    Using BeyondJS you get the slightly more verbose:

    var fibs = (0).lazy(1);
    fibs.extend(fibs.zipWith("+", fibs.tail());

    Summing the integers from 1 to 100:

    var sum = (1).lazy(100).fold("+");

    A nice thing about BeyondJS is that it works with IE5+ (most of the stuff works in IE4 as well), with Mozilla and with Rhino.

    Here is another cool example which works both using WSH and Rhino:

    File.StdIn.collect(function(line) { return line.split(",").reverse(); }).feed(File.StdOut);

    This code reads coma delimited data from the standard input and outputs it to the standard output with the column order reversed (note: requires a version of BeyondJS not yet online). Because File.StdIn is a lazy sequence of the input lines, the data is never wholly stored in memory.

    Suppose I only want to retain lines the contain the word ‘good’, regardless of case:

    File.StdIn.filter(/good/i).collect(function(line) { return line.split(",").reverse(); }).feed(File.StdOut);

    Note that while JavaScript is obviously not a pure functional language, you can use BeyondJS to write fully functional programs (pun intended) without any variables.

  6. Xy says:

    The function literal is very handy when defining neat Objects.

    function Car() {
    this.broom = function(loud) {

  7. General

    http://www.jnd.org/dn.pubs.html&amp;nbsp;- a collection of essays on various topics from design…

  8. adminadmin says:

    The Evolution of the Web Developer In the past, memory leaks haven’t posed huge problems for Web developers. Pages were kept relatively simple and navigation between different locations within a site was a great way to clean up any loose memory. If there..

  9. We’re getting hung up on the stack management aspects of recursive programming. Why do we need a stack

  10. H-bomb says:


  11. gheorghe says:

    Closers are a wonderful concept that works very well on all other languages that have it, even server side JavaScript. Too bad the implementers of JavaScript from browser makers have decided that garbage collection is done on two layers, one from page DOM and one from the JavaScript engine, so from what could be a great tool in making better code in a real functional way, we have to write procedural code because the language implementers messed up.

  12. 孙钰佳 says:

    不得不说Eric Lippert同志疾呼的:Don’t use closures unless you really need closure semantics. In most cases, non-nested functions are the right way to go. 是非常消极的应付之辞。今天关于IE内存泄漏的文章已有很多,而且很大部分就是微软的自己人在解释,甚至象Eric Lippert这样引擎开发组的成员。但是他们的文章始终没有正面承认其实这就是IE的bug,而且是非常严重的bug,这事情其实完全不关脚本引擎对象和DOM对象的事。就是微软对产品不负责任的表现,不说IE4,1997那个春天那是太遥远了点,但是IE6也是2001年随xp发布的。使用COM可以给他们的开发带来很多便利,当然也利用很多现成的东西,可是居然在带来这样的严重问题后,他们却把大部分责任归咎于不合理和不正确的使用Closures技术!对于循环引用产生Memory..

  13. freelancer says:

    mootools / prototype libraries heavily use closures, seems to be working ok on IE.

  14. Dave says:

    Isn’t this a bit head in the sand? Rather than fix your memory leak problems, you ask people not to use a fundamental and powerful part of JavaScript (or the hacked JScript). No other browsers seem to suffer in this way.

  15. EricLippert says:

    Dave, I wrote this article over five years ago. Those problems have been fixed in that time.

    However, I still stand by my advice. Using closure semantics _unnecessarily_ adds complexity to the analysis of a program that many people do not intend or fully understand, and that’s badness.

  16. A disclaimer first: This post will make sense to you only if you have read and understood my post on

  17. configurator says:

    Why does the circular reference matter here? The browser never tears down the div, the reference to the function remains anyway, the GC cannot collect. In which point did the reference the function had to the div matter at all?