Lazy Loading Functions

The best part about this Javascript pattern is the ability to calculate once and then use the new function definition from that point forward.

During the course of building web apps, we usually end up with functions to do certain tasks. However, since those tasks sometimes need to be done differently in each of the browsers, we end up with large if else statements to get the job done.

This is where Self Defining Functions come in handy.

Here is a simple Person Object that has a getPayInformation object. Lets assume for the sake of the argument that this function is called 100’s of times. In this case, each time the getPayInformation function is called, it first has to figure out the role, then do the calculations for the pay.

function Person(name, role) {
    if (!(this instanceof Person)){
        return new Person(name, role);
    }

    this.name = name || "John";
	this.role = role || "Guest";
};

Person.prototype.getPayInformation = function() {
	if (this.role === "Admin"){
		// fetch some data for the admin role. 
		// do some awesome calculations to munge the data 
		// ...
		return {
			"role"  : "Admin",
			"rate"  : 10.00,
			"hours" : 40
		};
	}else if (this.role === "CopyCat"){
		// fetch some data for the admin role. 
		// Calculating the Info for a copy cat is harder. Has some different calculations based on 
		// how many words they wrote
		// ...
		return {
			"role"  : "CopyCat",
			"rate"  : 37.00,
			"hours" : 23
		};
	}else if (this.role === "Crane Operator"){
		// fetch some data for the admin role. 
		// Calculating the info for a crane operator is based on hourly, anything over 40 is time and a half.
		// ...
		return {
			"role"  : "Crane Operator",
			"rate"  : 90.00,
			"hours" : 42
		};
	}else{ 
		// fetch some data for the admin role. 
		// we don't need to do anything for the guest, its always 0.
		// ...
		return {
			"role"  : "Guest",
			"rate"  : 0.00,
			"hours" : 0
		};
	}
}


What would happen if we knew that after the first time through this person was an admin. We would no longer need to do that check over and over again.

function Person(name, role) {
    if (!(this instanceof Person)){
        return new Person(name, role);
    }

    this.name = name || "John";
	this.role = role || "Guest";
};

Person.prototype.getPayInformation = function() {
	if (this.role === "Admin"){
		this.getPayInformation = function() {
			console.log("Lazy Function Definition");
			// fetch some data for the admin role. 
			// do some awesome calculations to munge the data 
			// ...
			return {
				"role"  : "Admin",
				"rate"  : 10.00,
				"hours" : 40
			};
		}
		return this.getPayInformation();
	}else if (this.role === "CopyCat"){
		this.getPayInformation = function() {
			console.log("Lazy Function Definition");
			// fetch some data for the admin role. 
			// Calculating the Info for a copy cat is harder. Has some different calculations based on 
			// how many words they wrote
			// ...
			return {
				"role"  : "CopyCat",
				"rate"  : 37.00,
				"hours" : 23
			};
		}
		return this.getPayInformation();
	}else if (this.role === "Crane Operator"){
		this.getPayInformation = function() {
			console.log("Lazy Function Definition");
			// fetch some data for the admin role. 
			// Calculating the info for a crane operator is based on hourly, anything over 40 is time and a half.
			// ...
			return {
				"role"  : "Crane Operator",
				"rate"  : 90.00,
				"hours" : 42
				};	
		}
		return this.getPayInformation();
	}else{ 
		this.getPayInformation = function() {
			console.log("Lazy Function Definition");
			// fetch some data for the admin role. 
			// we don't need to do anything for the guest, its always 0.
			// ...
			return {
				"role"  : "Guest",
				"rate"  : 0.00,
				"hours" : 0
			};	
		}
		return this.getPayInformation();
	}
}


Now, we only have to do the check once and then each subsequent calls can skip the check and just get to work.

So what does the output look like?

	var tammy = new Person("Tammy", "Admin");
	console.log(tammy.getPayInformation());
		"Lazy Function Definition"
		> Object
			{
				"role"  : "Admin",
				"rate"  : 10.00,
				"hours" : 40
			}
			
	var john = new Person("John", "Guest");
	console.log(john.getPayInformation());
		"Lazy Function Definition"
		> Object
			{
				"role"  : "Guest",
				"rate"  : 0.00,
				"hours" : 0
			}
	
	var lola = new Person("Lola", "CopyCat");
	console.log(lola.getPayInformation());
		"Lazy Function Definition"
		> Object
			{
				"role"  : "CopyCat",
				"rate"  : 37.00,
				"hours" : 23
			}
			
	var chad = new Person("Chad", "Crane Operator");
	console.log(chad.getPayInformation());
		"Lazy Function Definition"
		> Object
			{
				"role"  : "Crane Operator",
				"rate"  : 90.00,
				"hours" : 42
			}


Looks to be a pretty neat way to do Browser Feature detection instead of nested if statements. Moving to a Module pattern helps to support the Self Defining Function Pattern.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>