JavaScript Notes – 4 (Best Practices)

Posted: February 10th, 2012 | Author: | Filed under: technical | Tags: | Comments Off

In this blog article I want to discuss on few of the JavaScript best practices that I have gleaned from various people, talks, videos, books. For the sources, see here.

VAR, WHERE?

To start with declaration of variables. The best way to do it is

var oneVariable,
    anotherVariable,
    oneArray = [],
    oneObject = {};
// do your thing

Points to notes -
- Good formatting
- Initialization of arrays and object literals without using new is much cheaper (as scope resolution is not required).
- Do not forget the commas after each of the variables

Staying on the topic of variables, there is a useful-to-know concept of hoisting . The following code segment will elucidate the idea-

var foo = 1;
function bar() {
	if (!foo) {
		var foo = 10;
	}
	alert(foo);
}
bar();

Can you guess the output? Click show source below for answer and explanation.

/* the code above re-written to explain 
 * how the interpreter sees it
 */
var foo = 1;
function bar(){
    var foo; // the declaration of foo is hoisted to the top of the scope and undefined
    if(!foo){ // foo is undefined now, this foo not the global variable 
        foo = 10; // set the value of the local variable foo
    }
    alert(foo); // alert foo, the local foo 
}
bar(); // alerts 10

So that is the idea of hoisting explained simplistically. The lesson is to have all your var statements together at the top of the function to avoid such issues. There is something similar that happens with functions too, you can read more about it in Ben Cherry’s article. Long story short, you would want to define your functions before using them.

Do remember that JavaScript has function-level scope, not block level scope . You can create block level scope using anonymous, immediately-executing functions. I will do a more detailed blog post on JavaScript scoping and chaining later.

ARRAYS, LOOPS, YEAH TOGETHER

var a = [];
console.log(typeof a); // "object" Arrays are objects, not arrays. 
console.lo(a.length); // 0

a[10] = "nadu";
console.log(a.length); //11 

a["another_element"] = "another nadu";
console.log(a.another_element); // another_nadu
console.log(a.length); // 11 (still)

This means that arrays are slow, because they are effectively represented as objects. So, the easiest way to improve performance is to NOT do this

var i,
    elements = document.getElementsByTagName("div"); // a huge array
for(i=0; i<elements.length; i++){
    //add a class to the div
    // do something else
}

What is wrong? Well, in each iteration, the length of the elements array is calculated instead just cache the length in a variable and compare it with the loop variable. No big shakes at all right? Well do remember to do this for big arrays!

var i,
    elements = document.getElementsByTagName("div"), // a huge array
    l = elements.length;
for(i=0; i<l; i++){ 
    //add a class to the div
    // do something else
}

DOOM DOM

Few rules for manipulation of the DOM gleaned from this talk.

USE FRAGMENTS TO APPEND NEW ELEMENTS

Assume, you have a container div element and you want to create the child div elements after getting some JSON data from an external server. For appending the child elements,

var i,
    cDiv = document.getElementsById("container-div"), 
    l = jsonResponse.length ;
for(i=0; i<l; i++){ 
    var newChild = document.createElement("div");
    newChild.innerHTML = jsonResponse[i];
    cDiv.appendChild(newChild);    
}

The problem here is that if there are 100 children divs that are going to be created, then the live DOM will be modified 100 times for appending each child div and the performance takes a hit. Instead, the better method is to create a document fragment, append your nodes to the fragment and then attach the fragment to the live DOM.

var i,
    cDiv = document.getElementsById("container-div"), 
    frag = document.createDocumentFragment(),
    l = jsonResponse.length ;
for(i=0; i<l; i++){ 
    var newChild = document.createElement("div"); 
    newChild.innerHTML = jsonResponse[i]; 
    frag.appendChild(newChild);    
}
cDiv.appendChild(frag); // hurray only once do you touch the live DOM

Useful JavaScript Fact – Did you know that you do not need to convert your object keys to strings unless they are a keyword in JavaScript –

var obj = {
    "name" : "Nadu",
    "is_human": true
    "class": "Less Awesome"
}
// instead write 
var obj = {
    name : "Nadu"
    is_human: true
    "class" : "More Awesome"
}


Next planned article on jQuery and its goodness.

Credits

Ben Cherry’s (a Twitter Engineer) blog – http://www.adequatelygood.com
Paul Irish’s talk here