Lazy Function Definition Pattern

I am a little busy this week and did not make my regularly scheduled Tuesday post. To make up for it, today we will be discussing an interesting JavaScript pattern that you probably have not seen before, called Lazy Function Definition (as coined by Peter Michaux). Since everything in JavaScript is an Object, including Functions, you have the power to change and/or rewrite functions while executing inside their scope. Basically, you can update a Functions definition, on the fly, from the inside its scope. So if you have a repeating operation, such as a browser test, inside of a function foo() that is always the same for the current user and has to be repeated each time foo executes, then you can instead overload foo with the appropriate code the first that foo executes. Then each subsequent call, will not have the overhead of your browser test.

A simple example might be:

var getStartTime = function() {
	var t = new Date();
	getStartTime = function() {
		return t;
	}
	return getStartTime();
}

Assume, the Function getStartTime() is used to determine the time a process begins, such as once your JavaScript has started on a page. The first time you call it, the following happens:

  1. The variable t is set to the time that the function is first executed
  2. The global (window) scoped getStartTime() is then overloaded with a closure that returns the variable t; this does not conflict with the currently executing scope
  3. getStartTime() is re-executed inside of itself, but now it will return the value of t, from the closure

Then any future time you call getStartTime() you will always get the value of t as the closure is now the definition of the Function. This pattern is incredibly powerful when tuning your JavaScript, as: you do not need to define variables unless they are needed, those variables can exists as scoped (private) variables, and future calls to Functions using this pattern will be faster. We can apply this to attachEvent Function from last Fridays article, Xbrowser Event Handling:

var detachFunc = function();
var attachFunc = function(el, eType, fn, capture) {
	if (window.addEventListener) {
		attachFunc = function(el, eType, fn, capture) {
			el.addEventListener(eType, fn, (capture));
		};
		detachFunc = function (el, eType, fn, capture) {
			el.removeEventListener(eType, fn, capture);
		};
	}
	else if (window.attachEvent) {
		attachFunc = function(el, eType, fn, capture) {
			el.attachEvent(on + eType, fn, capture);
		};
		detachFunc = function (el, eType, fn, capture) {
			el.detachEvent(on&rsquot; + eType, fn, capture);
		};
	}
	else {
		attachFunc = function();
	}

	attachFunc(el, eType, fn, capture);
}

It is mostly safe to create the detach Function lazily along with the attach Function, because there are no events to detach if you have never attached any events. However, we have set detachFunc to an empty function, just in case your code accidentally tries to detach an event before it attaches it.

For another example, Dustin Diaz, recently used the Lazy Function Definition Pattern to illustrate how to improve his getXHR() method (the backbone of an AJAX system), in his article:

Faster Ajax