By:Tomas Kirda Posted On: Topic:Engineering

JavaScript Best Practices

 

The following is an article full of recommendations and general guidelines for writing clean JavaScript code. While our recommendations may change in the future as we build more sophisticated development tools or with new language features, one thing, however, will never change. You should write your code so that it is easy to understand. Ambiguity, thus, should be avoided at all cost. If you feel that your code is not clear enough for the future readers, please add a comment. Do this only to clarify your code as there is no need to have a life story in the comments. Remember: comments are messages from developer to developer.

Follow code conventions that are consistent in all your and your teammates' code. Here is a good list that you can use as a starting point: http://javascript.crockford.com/code.html

Use of Global Variables Should Be Minimized

Use namespaces for your code to organize it into modules and to avoid code collisions. Optimal number of global variables introduced is zero and if this is not an option then stick to one. Encapsulate your code inside anonymous function and execute the function immediately:

(function(){
    // Do stuff here
}());

When function is executed immediately after declaration wrapp it into parens. Use this code convention to indicate immediate invokation.

Use Single "var" Declaration per Scope

Since "var" accepts multiple declarations there is no reason to use more. All scope variables are moved to the top of the scope anyway (this is called hoisting). This may help reduce potential unexpected behavior in case duplicate names are introduced or some other logical mistakes are made.

(function(){

    var firstName = 'John',
        lastName = 'Doe',
        fullName = firstName + ' ' + lastName;
        
    // The rest of the function body
    
}());

JSLint is Your Friend

I can list many other things that are usually repeated in "JavaScript Best Practices" posts, but I would just be repeating what JSLint is going to tell you anyway.

JSLint

Warning! JSLint will hurt your feelings. That's how www.jslint.com greets its users and if you write sloppy code you will have to do a lot of fixing. But if you jslint it often you will develop proper coding style and discipline and it will become your friend that helps you spot minor mistakes that all of us humans make (code monkeys please ignore this part).

Use JSLint configuration at the top off each source file, so that you don't need to specify options each time you JSLint your code:

/*jslint browser: true, sloppy: false, eqeq: false, vars: false, maxerr: 50,
 indent: 4 */

You can set them up by checking/unchecking options at the bottom of the page and then copying and keeping them with your source code. Don't enable bad parts (such as tolerate == and !=) just to reduce number of errors, but update your code and eliminate bad parts from the source.

Let it know about all global declarations:

/*global jQuery, otherGlobalVariable */

Use Strict

Before ECMAScript 5 you were allowed to assign to variable that is not declared it would create it in a global scope:

(function(){
    name = 'John';
}());

With "use strict" you would just get an error:

(function(){
    'use strict';
    name = 'John';
}());

It helps you avoid introducing global variables inadvertently and spot errors early.

Module Pattern

Designate a single namespace for your application:

var App = (function () {
    'use strict';
    
    var settings;
    
    return {
    
        init: function(initialSettings){
            settings = initialSettings;
        },
        
        getVersion: function (){
            return settings.version;
        }
        
    };
}());

Keep code organized in modules. Augment application by attaching modules to it:

// Search module:
(function (app) {

    var module = {};
    
    module.find = function (query) {
        // Perform search
    };
    
    module.verifyQuery = function (query) {
        // Ver
    };
    
    // More module methods go here
    
    app.search = module;

}(App));

If you need or prefer to keep things private you may choose to use revealing module pattern:

// Search module:
(function (app) {

    // Private methods:
    
    function find(query) {
        // Perform search
    }
    
    function verifyQuery(query) {
        // Verify query
    }
    
    // Public methods:
    
    app.search = {
        find: find,
        verifyQuery: verifyQuery
    };

}(App));

Don't write functions that do everything. Write small functions that perform specific tasks rather than catch-all "smart" functions.

Development Code is for Developers

Do not write code for yourself. Write it for other developers who will take it over from you.

Prefer Clarity over Brevity. That means that function and variable naming should be meaningful rather than short. JavaScript compressor (Closure Compiler, YUI Compressor) will minify it for you if you end up with really long names. These rules apply to many other languages, too. The same goes the other way: things that work well in other languages may work well in JavaScript, too.

Log as much as you can. You may see logs in the console when you least expect them. It will help you have a better understanding what is going on, especially if the system is complex. This is very useful for other developer who will maintain the code in the future. Console can be a big time saver when trying to locate needed line of script or sometimes just to be aware what code is being executed. In Google Chrome it shows file and line from which it was called, too.

Be aware that code may brake if console is not present. To avoid errors replace it with fake console object and methods, when console is not present:

var console = window.console || {};
console.log = console.log || function(){};
console.warn = console.warn || function(){};
console.error = console.error || function(){};
console.info = console.info || function(){};

This is of course not necessary in the production code. Stripping this code can be built in into the build process, so that logging code is removed before compression and deployment to production. Following regex will strip all calls to console:

^\s*console\.(log|warn|error|info)\(.+\);\s*$

Visual Event is a bookmarklet which provides debugging information about events that have been attached to DOM elements. It can be big time saver when trying to locate what code is being called when an event is triggered.

Development code is for developers, production code is for machines. Therefore minimize and optimize code for production. Use build process to minify, optimize and combine code files.

It's How It Works, Not How It Looks

Don't add styling information using JavaScript, do it by manipulating CSS classes.

Don't rely on consistent structures or in other words don't add UI constrains for other developers that may work on the same application. What I mean by that is that you should not assume that when traversing DOM tree, that DOM element is what you think it is. Mark elements with CSS classes so that it serves as a marker at the same gives flexibility to maintain and change UI without affecting functionality.

Allow for Configuration

This includes labels, CSS classes, CSS namespaces, ID's and etc. By having configuration objects we make maintenance a breeze. That also opens many opportunities for customizations.

Optimize

Optimize your code. It's hard to come up with simplest solution right off the bat, so when refining your code look what you can remove or how can you simplify it.

You can create DOM elements in the loop but avoid inserting them into DOM. Keep DOM changes to the minimum. Avoid HTML creation in JavaScript as it's hard to keep track of the quality that is produced. Use prebuilt templates and keep templates where it's easy to maintain them.

Avoid hacking, try to analyze the problem and come up with reliable solution. Don't trust user data.

Never ever use JavaScript to protect sensitive or otherwise important data. If it's easy to write, it's easy to crack.

Tomas Kirda

Want more industry news?

comments powered by Disqus
Let's Talk