Closures, view from implementation perspective.

There are plenty of definitions of ‘closure’ term on the web. Most of them quite generic and here is my attempt to define what is the closure under the hood. Hope it will help to someone to understand better the subject.

Technically speaking closure is a data structure that combines reference to function body and non-empty list of call frames active at the moment of declaration.

Closure is created by executing some code that contains declaration of a function that uses variables from outer scopes. In this case VM (virtual machine), while executing the code, has to create not just reference to the function but closure structure – function reference and reference to its current environment[s] – list of call frames that hold used outer variables.

Here is JavaScript example of function that returns closure:

function Foo() {
   var zoo = 2;
   function Bar(p) {  
     return zoo + 2; // using 'zoo' variable from outer scope.
   return Bar; // returning inner function reference
var bar = Foo(); // here 'bar' contains Bar instance (the closure).
alert( bar() );  // invoking the function-closure.

In order Bar function to work it should have reference to outer call frame (the one that contained ‘zoo’ variable).

And here is an example of plain function declaration – function referred by bar uses only its own variables:

var baz = function() {
   var zoo = 2;
   return zoo + 2; // using 'zoo' variable from its own scope.

To represent JavaScript closure and plain function we can use following definitions (C++):

  struct Function { // plain JS function
    bytes bytecode; // executable code of the function.
  struct Closure {  // JS closure
    bytes bytecode;        // executable code of the function.
    cframe* cframe_chain;  // callframe chain, used to get/set variables in outer call frames.

If we don’t care too much about memory consumption then we can declare JS function as a generic class that will cover functions and closures in single entity:

  struct Function {  
    bytes bytecode;      // executable code of the function.
    cframe* cframe_chain_nullable; // callframe chain, is NULL for plain functions.

For any given JS function compiler can determine is it using outer variables or not. So it can tell if closure creation is required for given function declaration. It makes sense to do such detection as creation of closure is pretty expensive – VM shall move call frames from stack to the heap – convert callframes to GCable objects. If closure is not required by the nature of particular function VM should not create the closure and so heap will not be polluted by unused call frames.