Click here to Skip to main content
13,258,763 members (47,752 online)
Click here to Skip to main content
Add your own
alternative version


44 bookmarked
Posted 26 Jan 2008

Client-side Code Best Practices

, 13 Jan 2009
Rate this:
Please Sign up or sign in to vote.
This article demonstrates AJAX best practices based on ASP.NET AJAX.


While we develop AJAX applications, we often carelessly ignore giving up bad practices, which cause effects which are not so significantly visible when the site is not so large in volume. But, it often causes severe performance issues in the case of sites that make heavy use of AJAX technologies such as Pageflakes, NetVibes etc.

There are so many AJAX widgets in one page that minor memory leak issues combined may even result in a site crashing with a nasty “Operation aborted”. If there are a lot of WebService calls, and a lot of iterations among collections, inefficient coding in can make a site very heavy, resulting in the browser eating up a lot of memory, requiring very costly CPU cycles, and ultimately causing unsatisfactory user experience. In this article, many of such issues will be demonstrated in the context of ASP.NET AJAX.

Use more "var"

Less use of "var" can result in wrong calculations as well as errors in the logic. And also, the JavaScript interpreter will find it hard to determine the scope of the variable if var is not used. Consider the following simple JavaScript code:

function pageLoad()
    i = 10;
    alert(i);   // here, i = 100

function loop()
    for(i=0; i<100; ++i)
        // Some actions

Here, the loop uses the variable i that was used before in pageLoad. So, it brings a wrong result. Unlike .NET code, in JavaScript, variables can go along with the method calls. So, better not confuse the interpreter, and use more vars in your code:

function pageLoad()
    var i = 10;
    alert(i);   // here, i = 10

function loop()
    for(var i=0; i<100; ++i)
        // Some actions

Reduce scopes

It’s not pretty common. But, if you ever encounter such code, be sure it’s a very bad practice. Introducing more scopes is a performance issue for JavaScript interpreters. It adds a new scope in the ladder. See the following sample scope:

function pageLoad()
    function scope1()

        function scope2()

Introducing more scopes forces the interpreter to go through more sections in the scope chain that it maintains for code execution. So, unnecessary scopes reduce performance, and it’s a bad design too.

Careful with DOM element concatenation

This a very common bad practice. We often iterate through arrays, build HTML contents, and keep on concatenating into a certain DOM element. Every time you execute the block of code under the loop, you create the HTML markups, discover a div, access the innerHTML of a div, and for the += operator, you again discover the same div, access its innerHTML, and concatenate it before assigning.

function pageLoad()
    var links = ["", "", ""];

    $get(‘divContent’).innerHTML = ‘My favorite sites:<br />’

    for(var i=0; i<links.length; ++i)
        $get(‘divContent’).innerHTML += ‘<a href="http://www.’ 
        + links[i] + ‘">http://www.’ + links[i] + ‘</a><br />’;

However, as you know, accessing a DOM element is one the costliest operations in JavaScript. So, it’s wise to concatenate all HTML contents in a string and finally assign it to the DOM element. That saves a lot of hard work for the browser.

function pageLoad()
    var links = ["", "", ""];
    var content = ‘My favorite sites:<br />’

    for(var i=0; i<links.length; ++i)
        content += ‘<a href="http://www.’ + links[i] 
        + ‘">http://www.’ + links[i] + ‘</a><br />’;

    $get(‘divContent’).innerHTML = content;

Avoid using your own methods when there is a bult-in one

Avoid implementing your own getElementById method that will cause a script to DOM marshalling overhead. Each time you traverse the DOM, looking for certain HTML elements requires the JavaScript interpreter to marshall the script to DOM. It’s always better to use the getElementById of the document object. So, before you write a function, check if similar functionality can be achieved from a built-in function.

Avoid using Array.length in a loop

It's a very common reason for performance issues in AJAX. We often use code like the following:

var items = []; // Suppose a very long array
for(var i=0; i<items.length; ++i)
    ; // Some actions

It can be a severe performance issue if the array is so large. JavaScript is an interpreted language, so when the interpreter executes code line by line, every time it checks the condition inside the loop, you end up accessing the length property every time. Wherever applicable, if the contents of the array does not need to be changed during the loop’s execution, there is no necessity to access the length property every time. Take out the length value in a variable and use it in every iteration:

var items = []; // Suppose a very long array
var count = items.length;
for(var i=0; i<count; ++i)
    ; // Some actions

Avoid string concatenations, use array instead

Don't you think the following block of code has been written keeping every possible good practice in mind? Any option for performance improvement?

function pageLoad()
    var stringArray = new Array();
    // Suppose there're a lot of strings in the array like:
    stringArray.push('some content');
    // ... code edited to save space
    var veryLongHtml = $get('divContent').innerHTML;
    var count = stringArray.length;
    for(var i=0; i<count; ++i)
        veryLongHtml += stringArray[i];    

Well, as you see, the innerHTML of the div has been cached so that the browser will not have to access the DOM every time while iterating through stringArray, thus costlier DOM methods are being avoided. But, inside the body of the loop, the JavaScript interpreter has to perform the following operation:

veryLongHtml = veryLongHtml + stringArray[i];

And, the veryLongHtml contains quite a large string which means, in this operation, the interpreter will have to retrieve the large string and then concatenate it with the stringArray elements in every iteration. One very short yet efficient solution to this problem is using the join method of the array like the following, instead of looping through the array:

veryLongHtml = stringArray.join('');

This is very efficient than the one we were doing, since it joins the array with smaller strings, which requires less memory.

Introduce function delegates

Take a look at the following loop. This loop calls a function in each iteration and the function does some stuff. Can you think of any performance improvement here?

for(var i=0; i<count; ++i)

Well, for sufficiently large arrays, function delegates may result in significant performance improvement to the loop.

var delegate = processElement;
for(var i=0; i<count; ++i)

The reason behind performance improvement is, the JavaScript interpreter will use the function as a local variable and will not lookup in its scope chain for the function body in each iteration.

Introduce DOM elements and function caching

We have seen DOM caching before, and function delegation is also a kind of function caching. Take a look at the following snippet:

for(var i=0; i<count; ++i)

As you can figure out, the code is going to be something like:

var divContent = $get('divContent');
for(var i=0; i<count; ++i)

That is fine, but you can also cache a browser function like appendChild. So, the ultimate optimization will be like the following:

var divContentAppendChild = $get('divContent').appendChild;
for(var i=0; i<count; ++i)

Problem with switch

Unlike .NET languages or any other compiler languages, the JavaScript interpreter can not optimize a switch block. Especially when a switch statement is used with different types of data. It's a heavy operation for the browser due to conversion operations occurring in sequence; it's an elegant way of decision branching though.


In this article, we have seen many techniques for performance optimization in AJAX applications, and of course, these are not new and unique ideas, so you might find similar ideas else where as well.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Tanzim Saqib
Software Developer (Senior) British Telecom, Telerik, Pageflakes
Bangladesh Bangladesh

Tanzim Saqib is a Software Designer, video podcaster and Microsoft “MVP” in ASP.NET, who spent half of his life with software. He has been helping British Telecom build next generation SaaS portals. He builds Web 2.0 for Business architectures for 3.5 million BT Business users and complex widget ecosystem and CMS Framework for all the SaaS subsystems in BT.

In 6 years in the industry, he worked for companies like .NET controls provider Telerik, personalized Web 2.0 start-page Pageflakes, SaaS based CMS provider Sitemasher in Canada as well as total University Automation for AIUB. He started programming at 12, since then he developed many applications ranging from desktop utilities to banking solution for CitiBank, Wells Fargo, HSBC and so on. He is also a Technical Reviewer at Addison-Wesley Professional and technology speaker.

While he is not jamming with the latest technologies, he contributes to open source projects, writes articles for the community, and blogs. He holds a bachelor degree in Computer Science.

You may also be interested in...


Comments and Discussions

GeneralString concatenations Pin
E.F. Nijboer28-Oct-10 5:09
memberE.F. Nijboer28-Oct-10 5:09 
GeneralBest practices while writing ASP.NET code Pin
elizas27-Jan-10 2:07
groupelizas27-Jan-10 2:07 
it was a nice article.Even i want to share some best practices using code.
Use int.TryParse() to keep away from Exception.
While using Convert.ToInt32(), if the input parameter is of wrong format and if it can not be convertable into integer then an exception of type "System.FormatException" will be thrown, but in case of int.TryParse() no Exception will be thrown.

Convert.ToString() V/S obj.ToString()

Use Convert.ToString(), because if you are using obj.ToString() and the object(obj) value is null it will throw an excetion of type "System.NullReferenceException".
The cause of the exception is null doesn't have a method called ToString().

Response.Write("Name : " + Session["User_Name"].ToString()); //Here it will throw an Exception if Session["User_Name"] is null.
Response.Write("Name : " + Convert.ToString(Session["User_Name"])); //Here it will not throw any Exception.

String.Empty V/S ""
If you want to check whether a string is empty or not then use String.Empty instead of "", because "" will create a new object in the memory for the checking while String.Empty will not create any object, because Empty is a read-only property of String class.

So its better to use if("Devi" == String.Empty) instead of if("Devi" == "").

You can also use if("Devi".Length == 0) for doing the same thing but if the string is null then it will throw an exception of type "System.NullReferenceException".

String.IsNullorEmpry() V/S ("" || null)
Suppose you want to check a string for both its emptiness and nullability then its better to use String.IsNullOrEmpty() instead of ("" || null). Because "" will create a new object but String.IsNullOrEmpty() will not do so.

So its better to use if(String.IsNullOrEmpty("Devi")) instead of if("Devi" == "" || "Devi" == null)


GeneralNot AJAX best practices - just some JS ones. Pin
GilesHinton8-Apr-08 1:47
memberGilesHinton8-Apr-08 1:47 
GeneralVery useful article Pin
Ahsan Murshed7-Apr-08 21:16
memberAhsan Murshed7-Apr-08 21:16 
GeneralASP.NET AJAX Best Practices (Misleading header) Pin
harrym14-Apr-08 9:04
memberharrym14-Apr-08 9:04 
GeneralRe: ASP.NET AJAX Best Practices (Misleading header) Pin
joshc7-Apr-08 12:40
memberjoshc7-Apr-08 12:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171114.1 | Last Updated 13 Jan 2009
Article Copyright 2008 by Tanzim Saqib
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid