Writing Good Javascript

 

  1. Javascript Code Must Be browser compatible
  2. Naming Convention
  3. We should not write javascript code in .aspx file
  4. use try – catch in all functions / complex code blocks
  5. Javascript Code Must Be well aligned.
  6. Try to keep javascript file lighter + use prototype.js
  7. Define messages + regular expressions in a common place
  8. Always Use 'var'
  9. Detect special attributes before access
  10. Use second Bracket Notation
  11. Avoid 'eval'
  12. Avoid 'with' Statements
  13. Use onclick in anchors instead of javascript: Pseudo-Protocol
  14. Avoid document.all
  15. Don't use HTML comments in script blocks

 

 

Suggestions with small description

 

 

1.       Javascript Code Must Be browser compatible. We must check in FireFox and IE if javascript is working perfectly during development of a complex function. Not after completing all functions. It will save many hours which may need to re-code by checking all functions after error found.

 

Bad Example:

 

function IsNumeric() // this will not work in FireFox

{

KeyID = window.event.keyCode;

      

if( (KeyID >= 46  && KeyID < 58) ||KeyID < 32)

      {

            return true;

}

      else

      {

            return false;

}   

}

 

Good Example:

 

function IsNumeric(e)

{

   try

    {  

       var KeyID;

       var res = navigator.appName;

      

       if(res == "Microsoft Internet Explorer")

       {   

            KeyID = window.event.keyCode;

       }

       else

       {  

            strTemp = String.fromCharCode(e.which);

            KeyID = strTemp.charCodeAt(0);

       }

      

       try

       {

           if( (KeyID >= 46  && KeyID < 58) ||KeyID < 32)

           {

              return true;

           }

           else

           {

              return false;

           }

       }

       catch(ex)

       {}

    }

    catch(ed){}

   

   return true;

}

 

2.       Javascript variable names must have predefined prefix for different data types. We should use same prefix using in C# code. Plus some extra prefix for most common objects in javascript. For example, div for Div, tbl for Table, tr for TR, td for TD etc.

 

3.       We should not write javascript code in .aspx file. We can use separate single/multiple javascript file for each module.  

 

4.       We must use try – catch in all functions / complex code blocks. By this way javascript will not stop executing if an error occurred in one section.   

 

5.       Javascript Code Must Be well aligned. (Visual Studio 2005 does not align javascript code automatically. Even we can not align by pressing ctrl+k+d). We must keep alignment manually.

 

 

Bad Example:

 

function SetDivHeight()

{

var valu;

try{

 var obj1 = document.getElementById("Defaultbody");

 var objDiv = document.getElementById("divGrid");

 valu = obj1.offsetHeight;

// objDiv.style.height = "250";

    objDiv.style.height = valu - 50;

    //alert(valu);

    return;

 

 }

 catch(Ex)

 {}

 return;

}

 

 

Good Example:

 

function SetDivHeight()

{

var iHeight;

 

try

{

            var divBody = document.getElementById("Defaultbody");

var divGrid = document.getElementById("divGrid");

iHeight = divBody.offsetHeight;

      divGrid.style.height = iHeight - 50;

            return;

      }

      catch(Ex)

      {

      }

     

return;

}

 

 

6.       Try to keep javascript file lighter by removing unnecessary commented code blocks + by using small variable / function names.  We can use prototype.js javascript framework which has shortcut names for all-too-frequent long functions ($(), $$() , $F(), $A(), $H(), $R() etc). For example:

 

$(“divGrid”) is for document.getElementById(“divGrid”)

 

 

Bad Example:

 

function GetSalesOrderPageUrl()  // for Product Page(Details/Information)

{

 

//var url = "../CRM/AccountContactUI.aspx?NavigateId=" + DisplayPageUrl;

     var ifrmPage = GetElementByTagId("CurrentPageID","IFRAME");

     //var oSrc = queryStringC("NavigateIdF");

      var oSrc = "../Site.aspx?NavigateId=" + document.getElementById("hfOrderId").value;

//      var objUrl = document.getElementById("hfUrl");

     

  //    if(objUrl.value == "0")

    //  {

      // objUrl.value = oSrc;

      // }

//     return oSrc;  

    ifrmPage.src = oSrc;

 

var ChkInProgress = document.getElementById("ctl00_cphPage_rdInProgress");

       var ChkShipped = document.getElementById("ctl00_cphPage_rdShipped");

       var ChkPartiallyShipped = document.getElementById("ctl00_cphPage_rdPartially");

      

       var ChkReceived = document.getElementById("ctl00_cphPage_rdReceived");

       var ChkAuthorised = document.getElementById("ctl00_cphPage_rdAuthorised");

       var ChkPayCancel = document.getElementById("ctl00_cphPage_rdPSCancelled");   

          

           if(ChkInProgress.checked ||ChkShipped.checked ||ChkPartiallyShipped.checked)

                  if(ChkReceived.checked == false && ChkAuthorised.checked == false && ChkPayCancel.checked == false)

                  {

                    alert("Error Message");

                   

                   }

                   else

                     __doPostBack('ctl00$mnuPageToolbar','Save');

           else       

         __doPostBack('ctl00$mnuPageToolbar','Save');

}

 

Good Example:

function GetSalesOrderPageUrl()  // for Product Page(Details/Information)

{

var ifrmPage = GetElementByTagId("CurrentPageID","IFRAME");

var oSrc     = "../Site.aspx?NavigateId=" + $("hfOrderId").value;

ifrmPage.src = oSrc;

 

var chkInProgress       = $("ctl00_cphPage_rdInProgress");

      var chkShipped          = $("ctl00_cphPage_rdShipped");

      var chkPartiallyShipped = $("ctl00_cphPage_rdPartially");

      

      var chkReceived   = $("ctl00_cphPage_rdReceived");

      var chkAuthorised = $("ctl00_cphPage_rdAuthorised");

      var chkPayCancel  = $("ctl00_cphPage_rdPSCancelled");    

          

      if(chkInProgress.checked ||chkShipped.checked )

      {

            if(chkReceived.checked == false && chkAuthorised.checked == false)

            {

               alert("Error Message");

                   

            }

            else

            {

    __doPostBack('ctl00$mnuPageToolbar','Save');

}

}

      else       

      {

         __doPostBack('ctl00$mnuPageToolbar','Save');

}

}

 

7.       We should not use inline hard coded error success messages which are showed to user. Instead we should define messages at a common place, and then use only reference in codes. By this way it will be very easy to change message text / check grammar or spellings very easily. We can define very common messages in a common file. And other messages at the top of each javascript file.

 

Bad Example:

 

function ValidateFields()

    {

        RE_EMAIL_ADDRESS = /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/;

        email = document.getElementById('ctl00_cp_txtEmail').value;

        if( email == "" )

        {

            alert( "Please enter email");

            return false;

        }  

        if( !RE_EMAIL_ADDRESS.exec(email) )

        {

            alert( "Please, enter email address in valid format. i.e. yourname@yourservername.com.");

            document.getElementById('ctl00_cp_txtEmail').focus();

            return false;

        }

       

        return true;

}

 

Good Example:

 

try

{

/*================== Start Of Defining Messages =====================*/

var MSG_EMAIL_REQUIRED = "Please, enter email address in valid format.";   

var MSG_INVALID_EMAIL  = "Email address is required.";   

/*================== End Of Defining Messages =====================*/

/*=============== Start Of Defining Regular Expressions ===========*/

var RE_ZIPCODE = "/\d{5}(-\d{4})?/";

var RE_EMAIL   = "/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/";   

/*=============== End Of Defining Regular Expressions ===========*/

}

catch(ex)

{

               

}

 

 

function ValidateFields()

{

var txtEmail = $('ctl00_cp_txtEmail').value;

if(txtEmail == "" )

{

alert(MSG_EMAIL_REQUIRED);

return false;

}  

if( !RE_EMAIL.exec(txtEmail) )

{

alert(MSG_INVALID_EMAIL);

$('ctl00_cp_txtEmail').focus();

return false;

}

       

return true;

}

 

 

8.       Always use ‘var’. it is good practice to use var as there are two cases in functions where it is necessary:

   If a global variable of the same name exists.

   If recursive or multiple functions use variables of the same name.

 

Bad Example:

 

MSG_EMAIL_REQUIRED = "Please, enter email address in valid format.";   

MSG_INVALID_EMAIL  = "Email address is required.";   

 

Good Example:

 

var MSG_EMAIL_REQUIRED = "Please, enter email address in valid format.";   

var MSG_INVALID_EMAIL  = "Email address is required.";   

 

 

9.       Detect special attributes if exists before use. To make our code browser compatible it is important to check if the attribute is valid or not in current browser.   For example the attribute window.event.keyCode is not supported by FireFox. So we should write

 

Bad Example:

var KeyID = window.event.keyCode;

 

Good Example:

 

if(window.event.keyCode)

{   

KeyID = window.event.keyCode;

}

 

 

10.   Use second bracket indexing instead of dot notation to access attributes. It will help us to access attributes within loop. For example, we can access myObj[“value”+i] but can not access myObj.value+i

 

Bad Example:

var txtName = document.formName.name.value;

 

Good Example:

 

var txtName = document.forms["formName "].elements["name"].value;

 

 

11.   Avoid using eval(). "Eval is evil." Don't use it unless you are an experienced developer and know that your case is an exception. Normally you can access useing second bracket notification instead of eval().

 

Bad Example:

var txtName = eval(“document.formName.name”+i+”.value”);

 

Good Example:

 

var txtName = document.forms["formName"].elements["name"+i].value;

 

 

12.   Avoid using document.formName. Though some browsers make the form available as a property of the document itself using its name. This is not reliable and shouldn't be used.

 

Bad Example:

var txtName = document.formName.name;

 

Good Example:

 

var txtName = document.forms["formName "].elements["name"];

 

 

13.   Avoid using the “with” statement. This is often used as a shortcut to avoid multiple long references.

But the problem is that the programmer has no way to verify that input1 or input2 are actually being resolved as properties of the form elements array. It is checked first for properties with these names, but if they aren't found then it continues to search up the scope chain. Eventually, it reaches the global object where it tries to treat "input1" and "input2" as global variables and tries to set their "value" properties, which result in an error.

 

Instead, create a reference to the reused object and use it to resolve references.

 

Bad Example:

with (document.forms["mainForm"].elements) {

   input1.value = "junk";

   input2.value = "junk";

}

 

Good Example:

 

var elements = document.forms["mainForm"].elements;

elements.input1.value = "junk";

elements.input2.value = "junk";

 

 

14.   Use onclick In Anchors Instead Of javascript: Pseudo-Protocol. Also remember that the word is onclick. Not onClick .

 

Bad Example:

 

<a href="javascript:doSomething()">link</a>

<a href="#" onClick="doSomething()">link</a>

<a href="#" onClick="javascript:doSomething();">link</a>

<a href="#" onClick="javascript:doSomething(); return false;">link</a>

 

Good Example:

 

<a href="somepage.aspx" onclick="javascript:doSomething(); return false;">link</a>

 

 

 

15.   Avoid using “document.all”. It was introduced by Microsoft in IE and is not a standard javascript DOM feature. Although many newer browsers do support it to try to support poorly-written scripts that depend on it, many browsers do not.

 

Bad Example:

 

var frmMyForm = document.all("mainForm”);

 

Good Example:

 

var frmMyForm = document. getElementById("mainForm”);

 

16.   Don't Use HTML Comments In Script Blocks. No browsers in common use today are ignorant of the <script> tag, so hiding of javascript source is no longer necessary. In fact, it can be considered harmful for the following reasons:

 

i) Within XHTML documents, the source will actually be hidden from all browsers and rendered useless

ii) -- is not allowed within HTML comments, so any decrement operations in script are invalid

 

Bad Example:

 

<script language="javascript">

<!--

   // code here

//-->

</script>

 

Good Example:

 

<script language="javascript">

   // code here

</script>