JavaScript Design Patterns

11:19 AM Xun 2 Comments

You may say JavaScript is at its golden age now, it reigns as the indisputable language of the web. With the demand comes the supply. Over the past 5 or 6 years, over 100 of JavaScript libraries have sprung up, some of them aiming at solutions for common tasks such as event handling, dom traversal, standard AJAX call, others intends to provide a framework upon which programmers can readily extend and deploy.


So did various design patterns in JavaScript emerge.

What are design patterns?

In JavaScript or software engineering in general, "a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. A design pattern is not a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations. "
Software design pattern


Why design patterns in JavaScript? Well, first of all, no, you do not have to use any design patterns. However like how JavaScript libraries can make your life easier, design patterns probably can make your code cleaner and more robust especially as the application is getting more complex. JavaScript is an extremely flexible language, it is loosely-typed, its functions are first-class objects that can be created and passed around dynamically. The only scope is functional scope, anything outside of a function is global and can be accessed and modified. All of this flexibility is a double-edged sword can spell power and potential for misuse or abuse.

In the realm of software engineering, design patterns are categorized as creational, behavioral, structural, etc. To me, specific to JavaScript, there are two camps. One camp is specifically designed to deal with the evils and peculiarities of JavaScript, such as Singleton Pattern for global variables, Module Pattern for clear separation of private and public variables; The other more conforms to the general object-oriented thinking, such as Factory Pattern, Composite Pattern.

In the following, we will only take a look at the JavaScript specific patterns.

Singleton Pattern

You may have been using the Singleton pattern all the while. In its simplest form, a singleton looks like this:

var Person = {
name: "John Doe",
age: 30,

talk: function(){
},

wak: function(){
}
}


That is it. An object literal that groups the attributes and methods together into one logic unit. Or namespacing.

Singleton can be used as a page-specific wrapper.


Project.page1 = {
variable1: xxx ,
variable2: xxx,
init: function(){

}

};

document.ready{
project.page1.init();
}

Module Pattern

Module pattern is a more advanced singleton pattern, in that it separates private members from public ones. Module pattern has been cemented by the blog post A JavaScript Module Pattern.

A typical module pattern has the following elements:
a) A closure set up by anonymous functions;
b) private members, all declared as local variable with var ;
c) public members inside the return block, returned as an object literal ;

JavaScript uses anonymous functions a lot:


(function() {

// ...

}());

The above creates an anonymous function, it also attaches a pair of parenthesis so the function can be executed right away.

Inside the anonymous function, we set up closures to separate private and public members. In a singleton pattern, everything is equally accessible and readily to be modified. Closures however set up outer and inner scope in a function; The outer scope is created by the outer function that wraps around a set of (private) variables and functions marked by the keyword var, the inner scope/functions live within the larger function and have access to all the variables, only those functions and variables returned by the outer functions are public.


The following is a dummy module pattern:


Module_Person = (function () {
//private sections
var name = "John doe";
var age = 30;

var talk = function () {
};

var walk = function (x) {
}
// public sections
return {
statement: "I am a person created in the module pattern",
publicTalk: function () {
alert(this.statement);
}
}
} ());

Module_Person.publicTalk();

alert(Module_Person.statement + " statement");

Lazy initiation

Module pattern is great and it gets executed as soon as the script loads. However sometimes you may not want this to happen, especially if the module is resource heavy. In this case, you may want to modify the pattern further more so you have full control when it gets instantiated.

The way do it is to future package your pattern, put all of the module instantiation into a constructor function, and add a instance variable, then in the return statement check if the module has ever been instantiated, if yes, return the instance, if not create one and return.

With this in mind, the above module pattern can be modified into a lazy loading one.


LazyLoading_Module_Person = (function () {

var person=null;
//private sections
function module_person () {
var name = "John doe";
var age = 30;

var talk = function () {
};

var walk = function (x) {
}
// public sections
return {
statement: "I am a person created in the module pattern",
publicTalk: function () {
alert(this.statement);
}
}
};

return {

getPerson: function () {

if (person === null) {

person = new module_person();
}

return person;
}
}

} ());

LazyLoading_Module_Person.getPerson(); // get instantiated the first time

LazyLoading_Module_Person.getPerson(); // simply return the instance






Chaining

We have seen so often the weirdly appealing operation chain in JQuery, where the dollar sign ($) forks together a long sequence of operations on a set of elements. Chaining serves two purposes: less code and more efficiency, in that to do several things on the same object, the object needs to be fetched only once and operations can be piped onward in a streamlined fashion.

JQuery has made chaining a well-known JavaScript pattern. How does it work?

In JavaScript all objects are passed as references, and all objects inherit from their prototypes.

Thus you can create a operation chain by bassing the reference back by calling return this at the end of every method

As a practice, I created my dummy operation chain


//construtor
function Clean_Talk(text) {
this.talk = text;
}

// function prototypes
// return the reference to This back at end of each method
Clean_Talk.prototype = {

modify: function () {
this.talk = "Cleaned Talk: " + this.talk;

return this;

},

filter: function () {
this.talk = this.talk.replace(/badword|anotherbadword/gi, "****");
return this;
},

speakNow: function () {
alert(this.talk);
}

};

var clean_talk = new Clean_Talk("I said some badword. Can you filter it out?");
clean_talk.modify().filter().speakNow();


Outside of JQuery, we found other elegant use of chaining at http://ajaxian.com/archives/javascript-asynchronous-method-queue-chaining

Source:
Pro JavaScript Design Patterns

2 comments:

  1. LazyLoading_Module_Person.getPerson(); // simply return the instance

    is wrong, please use alert(LazyLoading_Module_Person.getPerson()) to check ,it is undefine.

    ReplyDelete
  2. You are absolutely right. Made the change.

    ReplyDelete