Monday, October 18, 2010

Javascript patterns and antipatterns

Original post here



This most likely is just the first in a series of posts on the matter. Let me preface this post with the thought that I've come across quite a bit of code in my professional life. When I was a bit younger and happened to come across a piece of code that I knew was horrible, I'd was for the most part apathetic. But since being heavily involved in core Javascript for the past year from writing plug-ins to playing around with server-side JS and everything in-between, I've come across not only bad legacy JS, but dangerous JS that really does more damage than good. I guess this is to be expected because JS is so easy to get something going without know what is being done.

I admit that starting out I too fell victim to common bad practices, or antipatterns. It was only natural that I learned from reading someone else's solution to a problem without going into detail of what the language was actually doing; I wasn't concerned with that at the time. This is no longer the case since JS has gain tremendous traction in the development role. In order to have super premium code that will preform the way that it is expected to without doing harm to others code is to: seriously know the language inside and out along with adhering to certain design patterns that will not only be optimized, but safe, clean and easy to read.

Here is my little attempt to show little snippets that I've learn along the way that are essential for me to be 100% confident in my code.

One of the most common antipatterns that I've come across is the overuse of global variables. Yes, they are quick and easy but also potentially dangerous, not to mention annoying. But aside from my personal annoyance at the sloppy coding, JS does have some bugs within the language can have unforeseen consequences on the sloppy code. Along with the overuse of global variables, are sometimes the way the variables are defined.


// global namespace
myVar = 5; //antipattern
var myVar = 5;


Both of these statements are valid, and for the most part they will do what the author expects them to do, but they are different. The variable lacking the 'var' is called an implied global and the other is an explicitly defined variable.


// antipattern
function MyFunction( args1 ) {
myVar = 5;
if ( args1 === myVar ) {
return true;
}
return false;
}


This function is easy enough, it checks the parameter passed in with the author's intended local variable 'myVar'. Since myVar in this example is defined without 'var', it is an implied global. What author might not have intended is now 'myVar' has been added to the global namespace which can cause problems if there are variables already defined with the same name.

Corrected:

// correct pattern
function MyFunction( args1 ) {
var myVar = 5; //corrected
if ( args1 === myVar ) {
return true;
}
return false;
}


Another different between implied globals and explicit ones, or ones defined with 'var' is the ability to delete the variable if wished. It is safe to say if a global variable is necessary it most likely shouldn't be deleted and be available through the program's life-cycle. Variable that are implied globals can be deleted and explicit cannot. Seeing why this is a problem requires you to take a step back and see the true purpose of a global variable. Implied globals can be deleted which means that they are properties or elements of the global object. This is undesired for the purpose of truly using a global variable. Lastly, since we are working with Javascript and not the DOM 100% of the time, adding elements or global variables to the window object on DOM is ill-advised. To have your program less prone to bugs while still relying on using global variables no matter what environment you may be working in, create your own global object.


var globalObj = (function () {
return this;
}() );