Javascript context holder pattern

Recently I was writing some OOP javascript for browser. Javascript is different from other OOP languages like C++,  C#, or Java. So, if you are not familiar with the differences and some extra capabilities of javascript, it’s really easy to get into horrible problems. One of those are context object aka this.

this keyword is a reference holder to an object. Now, in javascript, it’s the context object. Context object is a thing that depends on the context a function is being called. So, this changes and points to the current context object! Before you read further down, get yourself familiar with javascript function context and how to switch between them.

Let’s start with a dummy Stats class which simply pulls a number from server periodically and renders into an html element. So, we can have a set of counters which periodically updates!


function Stats( selector, timeout ) {

	this.hits = 0, // data
	this.selector = selector, // a selector where data is rendered
	this.timeout = timeout, // period on which data is fetched from server

	this.getHits = function () {

		return this.hits;

	},

	this.setHits = function ( hits ) {

		this.hits = hits;

	},

	this.loadHits = function () {

		// comes from server with ajax. we are pretending here.
		var hits =  this.getHits() + 1;

		this.setHits( hits );
		// render codes omitted

	},

	/*
	this is the method that will schedule
	a periodic job to pull data from the server
	*/
	this.run = function () {

            // definition of run with setInterval method

	}

}

var visitorStats = new Stats("#visitorSpan", 2000); // our visitor stats instance
visitorStats.run();

Now how do we define the run function so that it calls the getHits method of the visitorStats object? The following is the first mistake!


	this.run = function () {

		setInterval( function ()  {

			/*
			this is inside of a anonymous method
			and the context object of this anonymous
			method is "<strong>window</strong>" object!!!! And window object
			dont have a loadHits method!
			*/

			this.loadHits();
			// Uncaught TypeError: this.loadHits is not a function

		}, this.timeout )

	}

So, how do we access the visitorStats object? Let’s first try to remove the anonymous function

	this.run = function () {

		setInterval( this.loadHits, this.timeout )

	}

Now you run into a different error like “Uncaught TypeError: this.getHits is not a function”. If you debug the this object inside getHits, you would find the window object again! How is this happening? This is because you are passing the function handle/reference to setInterval method which asynchronously and simply calls the method. All the methods by default has the window context attached to it.

Context is King

So, I created a context holder pattern which works in anonymous methods, asynchronous methods, etc!


	this.run = function () {

		holder = this;
		/* here <strong>this</strong> points to the context object of
		"run" method-call ( not method ) because it's still
		inside the run method
		*/

		setInterval( function () {

			holder.loadHits();
			// now javascript cannot switch the context!

		}, this.timeout )

	}

So, be careful about context object and use holder pattern whenever you are stepping out of the current context. Like inside jQuery ajax!

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