Getting Closure.

Mark Dalgleish
Web Directions Code '12
bit.ly/gettingclosure

A little about me.

UI Engineer, Aconex

Slides built with Fathom.js

Immediately Invoked Function Expressions

aka IIFE (pronounced "iffy")
Coined by Ben Alman, @cowboy

(function(){
    
  // Code goes here...
  
})();

"Immediately Invoked"?

The function expression is called once as soon as it is evaluated and never run again.

(function(){
    
  // Any code in this function
  // is run immediately
  
})(); //<-- Brackets invoke the function

"Function Expression"?

There are two ways of defining functions:

// Function declaration:
function foo() {  }

// Function expression:
var foo = function() {  };

Why is the difference so important?

You can only immediately invoke function expressions, not function declarations.

// This is NOT valid syntax:
function() { /* ... */ }();

// The parentheses around the function
// turn it into a function expression
(function() { /* ... */ })();

Do we always need the parentheses?

// Function expressions don't need them...
var foo = function() { /* ... */ }();

However, this is the preferred syntax:

var foo = (function() { /* ... */ })();

The parentheses help indicate that it's an IIFE.

Turning declarations into expressions

Although parentheses are the preferred method, any of the following will also work.

!function() { /* ... */ }();
+function() { /* ... */ }();
-function() { /* ... */ }();
~function() { /* ... */ }();
new function() { /* ... */ };
new function(arg) { /* ... */ }(arg);

IIFEs in the wild: jQuery

First and last lines of the jQuery source:

(function( window, undefined ) {
    
  // Snip...
  
})( window );

Notice var called 'undefined', which is undefined.

IIFEs in the wild: jQuery Plugins

Seal your code in a new scope, alias the global jQuery function as $:

(function( $ ) {
    
  // Snip...
  
})( jQuery );

IIFEs in the wild: Backbone.js

First and last lines of the Backbone.js source:

(function(){
    
  // Snip...
  
}).call(this);

Notice Backbone.js uses the 'call' syntax variation.

IIFEs in the wild: CoffeeScript

First and last lines of any script compiled from CoffeeScript using default settings:

(function() {
    
  // Snip...
  
}).call(this);

IIFEs in the wild: requestAnimationFrame

Animation loop which runs immediately and calls itself again once completed.

(function animloop(){
  window.requestAnimationFrame(animloop);
  render();
})();

Protect against unwanted globals

/* lib.js */
(function() {
  window.public = 'foo';
  var private = 'bar';
})();

/* script.js */
public; // 'foo'
private; // undefined

Compute & return a value in one statement

Returning from an IIFE evaluates to a single value:

var browser = {
  vendorPrefix: (function(){
    var prefix;
    // Detect vendor prefix...
    return prefix;
  })()
};

Create a "class" in one statement

var MyClass = (function(){
  function MyClass(foo) {
    this.foo = foo;
  }
  MyClass.prototype = {
    bar: 'baz'
  };
  return MyClass;
})();

CoffeeScript classes use IIFEs:

class Foo //Compiles to:
var Foo;
Foo = (function() {
  Foo.name = 'Foo';
  function Foo() {}
  return Foo;
})();

Emulate block scope

for (var i = 1; i <= 3; i++) {
  (function(i){
    // All variables (including i)
    // are now scoped to this block
    
    // On click, alerts '1', '2' and '3'
    $elem.click(function() { alert(i); });
  })(i);
}

Why pass 'i' to the for-loop IIFE?

Javascript has lexical (function) scope, so i is shared by all functions created in this loop.

The IIFE locks in i's value, otherwise we get this:

for (var i = 1; i <= 3; i++) {  
  // On click, alerts '4', '4' and '4' :(
  $elem.click(function() { alert(i); });
}

CoffeeScript's "do" === instant IIFE

do (i) ->
  console.log i

Compiles to:

(function(i) {
  return console.log(i);
})(i);

Create private variables

The revealing module pattern ('num' is private):

var number = (function(){
  var num = 0,
      add = function(n) { num = num + n; },
      get = function() { return num; };
  
  return { add: add, get: get };
})();

Create private functions

var foo = (function(){
  var priv = function() { alert('Hi!'); },
      publ = function() { priv(); };
  
  return publ;
})();

'foo' is now a function that calls the private 'priv' function (available via a closure).

IIFE !== Closure.... so what is a closure?

A closure is created when a function is returned from another function, retaining its original scope.

var foo = (function() {
  var bar = 'baz';
  return function() { return bar; };
})();
foo(); // Returns the value of 'bar'
bar; // Undefined, out of scope

Using closures to fix lack of block scope:

function makeAlert(i) {
  return function() {
    alert(i)
  }
}
for (var i = 1; i <= 3; i++) {  
  // On click, alerts '1', '2' and '3' :D
  $elem.click(makeAlert(i));
}

IIFE !== Self-Executing Anonymous Function

What IIFEs used to be called (mistakenly).

Why is this term incorrect?

  • IIFEs don't execute themselves, they are invoked like any other function.
  • They don't have to be anonymous, it's only important that they're function expressions.

A Real Self-Executing Anonymous Function

This anonymous function literally executes itself:

var foo = function() {
  if (arguments.callee.caller ===
      arguments.callee) {
    return; // ...if foo called foo
  }
  arguments.callee(); // <- Self-execute
};

ES5 Strict and Named Function Expressions

In ECMAScript 5, 'arguments.callee' is deprecated in favour of using named function expressions:

var foo = function bar() {
  if (bar.caller === bar) {
    return;
  }
  bar();
};

Wrapping up: Why are IIFEs useful?

  • Used to seal code inside a new scope and prevent unwanted global variables.
  • Allow you to compute and return a value (e.g. "classes") where only one statement is allowed.
  • Required to emulate block scope (pre ES6's 'let').
  • Useful in creating private functions and variables using closures.

Thanks for watching.