Closures with JavaScript and Python

Closures are functions or references to functions that hold within their scope non-local variables. This variables endure beyond their existence outside of these functions scope. These variables are therefor enclosed within the lexical-scope of that functions.
This is particular useful for JavaScript where with every function call (even if the same is called recursively) a new execution context is created, and an automatic garbage collection throws out all contexts with no reference. For a detailed explanation Jim Ley’s description of closures in JavaScript has proven itself as a great resource.

To create closures in JavaScript one has to assign a reference to a nested function (inner function) declared within a different function object. The garbage collection than can not remove the execution context of that function, as there still exists an object holding a reference to it. And this inner function holds the scope of the outer function even though  that function has already returned. Here is a simple example to explain:

function counterscope() {
  var counter = 0;
  function f() { return counter++; }
  return f;
}
var count = counterscope();
var count2 = counterscope();
console.log(count());  // 0
console.log(count());  // 1
console.log(count2()); // 0 -> references different/new scope
console.log(count());  // 2

counterscope()  returns a declaration of an inner function f , which as to the lexical-scope of JavaScript inherits the scope of counterscope() , namely the variable counter . This means f holds a reference to counter, while counter may no longer exist in the context of counterscope() as this function returns. count is the property holding the reference to f and we can execute it repeatedly changing the variables state in the local context. count2  also holds a reference to f with it’s own scope, as we can see upon execution of count2().

This post can only provide you with a rough understanding of closures in JavaScript. Having a good understanding of closures, can be very important to JavaScript development as it is such a common and useful pattern. The same probably holds true for the Prototype concept of JavaScript. Reading through the here provided references should help you getting comfortable with closures.

But how are closures useful? For example you can use the inherit context as a cache storing the result of a long calculating function or implementing private members to JavaScript objects as described here: Private Members in JavaScript

Let’s see how we could implement a local function cache with closures and JavaScript, and Python.

var calc = (function executeFunc(){
    var cache = [];
    return function calc(x){
      if(cache[x]){
        console.log("Cache hit: "+ cache[x]);
        return cache[x];
      }
      cache[x] = x+10;
      return cache[x];
    }
})();
console.log(calc(10));
console.log(calc(20));
console.log(calc(10)); // cache hit
console.log(calc(30));
console.log(calc(20)); // cache hit

Here the closure cache[] is used to store the results of our very complicated calculation. This example is also slightly different from the previous as we here use an anonymous function ()() to build up the enclosing scope. Let’s now see how we can implement the same functionality with Python.

Closures in Python work quit similar to JavaScript. A function declaration is returned from a different function object. The caching example from JavaScript in Python looks as follows:

def calcFunc():
  cache = {};
  def calc(x):
    if x not in cache:
      print "Cache miss."
      cache[x] = x + 10
    return cache[x]
  return calc

count = calcFunc()

print count(10) // Cache miss. 20
print count(10) // 20

So what we see here is the use of closures in Python. As if in JavaScript a function declaration is returned which captures the scope of the enclosing function that returns it.

Further Readings:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s