0% found this document useful (0 votes)
43 views

DHTML Javascript Coding Guidelines 2

This document outlines best practices for developing DHTML/JavaScript code. It discusses guidelines for code style, architecture, performance, and design patterns. Key guidelines include using consistent naming conventions, avoiding circular references between code and DOM elements, leveraging browser capabilities through CSS, and structuring code into reusable components through prototype-based inheritance.

Uploaded by

Garima Agarwal
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views

DHTML Javascript Coding Guidelines 2

This document outlines best practices for developing DHTML/JavaScript code. It discusses guidelines for code style, architecture, performance, and design patterns. Key guidelines include using consistent naming conventions, avoiding circular references between code and DOM elements, leveraging browser capabilities through CSS, and structuring code into reusable components through prototype-based inheritance.

Uploaded by

Garima Agarwal
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

DHTML/JavaScript Coding Guidelines

Author: Aamer Hydrie

This document outlines best practices for developing code in DHTML/JavaScript. It’s meant
to be a living document that reflects our collective wisdom of what works and what doesn’t.
A best practice could exist for one or more of these reasons –

 It makes the code more readable


 It makes the code more maintainable
 It makes the code more scalable
 It improves performance
 It improves security
 Others?

Style Guidelines

1. General
 Tabs should be 4 characters wide

2. Add comments to your code


Comments and whitespace can be stripped out during the “build”

3. Naming conventions

 Use UpperCamelCase for class names


 Use lowerCamelCase for function names, properties, method names, parameters
and local variables
 Do not abbreviate or shorten names. For example, do not shorten
‘sourceElement’ to ‘srcEl’
 Use a ‘g’ prefix for variables with global/’window’ scope. E.g. ‘gSidecar’
 Use a ‘_‘ prefix for private members of a JavaScript class. E.g.
‘_contentDocument’
 Use a ‘k’ prefix for constants. E.g. ‘kDefaultWidth’

4. Braces
The opening brace should be on the line following if, for, while, etc.
Always use an opening and closing brace

if(a > 4)
{
a++;
}
Architectural Best Practices
1. Declare your DOM elements
In DHTML, it’s possible to generate HTML elements dynamically using JavaScript. While this
is unavoidable in some situations; dynamic elements make your code harder to read, debug
and maintain. Whenever possible, declare your DOM elements in HTML.

2. Style your elements in CSS


DOM elements should be positioned and styled in CSS. This creates a clean data-view
separation and allows the style and layout of a page to be manipulated independently of the
data or code. Whenever possible, this practice should also apply to dynamically generated
elements.

3. Write browser portable code


Many common operations require different calls depending on the host browser. Browser
specific code should be factored out into a browser independent function. This provides a
clean abstraction and a single place to add support for additional browsers in the future.
Browser independent code is currently collected in ‘common.js’ (note – need a single
location for common code).

4. Factor your code into components


While JavaScript doesn’t have native support for classes, it’s still possible to apply object
oriented techniques in JavaScript. See the component pattern in the Patterns section for a
template JavaScript class.

Performance Best Practices

1. Use browser flow whenever possible (aka avoid absolute positioning)


Every browser page has a natural flow that determines the position of DOM elements. While
DOM elements can be explicitly position using absolute positioning, using the browser to
position elements using the flow is far more performant.

2. Use CSS pseudo classes whenever possible


CSS defines several pseudo classes such as ‘hover’, ‘active’, ‘visited’. Pseudo classes can be
used to generate effects such as changing the background color while hovering over an
element. Using these pseudo classes is far more performant than implementing your own
‘onmouseover’ and ‘onmouseout’ event handlers.

.loginbutton
{
background-color:White;
}

.loginbutton:hover
{
background-color:Red;
}

3. Avoid circular references between the DOM and JavaScript


It’s a common pattern to have related DOM elements and JavaScript objects refer to one
another.
For example, the code snippet below the JavaScript object saves a reference to the DOM
object. It then goes on to create a circular reference by using an expando property on the
DOM object to refer back to the JavaScript object.

function MyComponent(element)
{
...

// Reference from JavaScript to DOM


this._panel = document.getElementById(‘uxPanel’);

// Reference from DOM to JavaScript


this._panel.componentInstance = this;
}

This kind of circular reference can cause memory leaks if it’s not explicitly broken by the
application. One way to avoid this is to refer to the DOM object by id.

If you must create a circular reference in your application, make sure you break it explicitly
when you’re done using the referenced objects.

4. Use closures judiciously (for event handlers)

Closures are useful constructs in JavaScript. Typically, a closure is an anonymous function


with the execution context and variables needed for execution. For example, the event
handler below is a closure.

function MyComponent(element)
{
...

var i = 10;
element.onclick = function(e)
{
i++;
...
}
}

While closures are a convenient construct, their use can inadvertently cause circular
references between DOM objects and JavaScript objects.

For example, in the listing below, using a closure creates a circular reference through the
closure scope variable ‘panel’.

function MyComponent(element)
{
...

var panel = document.getElementById(‘uxPanel’);


panel.onclick = function(e)
{
i++;
...
}
}

The circular reference above could be eliminated by explicitly setting ‘panel’ to null.

function MyComponent(element)
{
...

var panel = document.getElementById(‘uxPanel’);


panel.onclick = function(e)
{
...
}
panel = null;
}

Another way to get rid of the circular reference is to avoid using the closure altogether

function MyComponent(element)
{
...

var panel = document.getElementById(‘uxPanel’);


panel.onclick = myClickHandler;
}

function myClickHandler()
{
...
}

5. Check your code for memory leaks


Memory leaks can occur in JavaScript due to circular dependencies or the incorrect use of
closures. Check your application for memory leaks by monitoring memory usage in Windows
Task Manager. Read this excellent article on the possible memory leaks you may encounter
in JavaScript.

Design Patterns and Templates


Pattern 1 - Writing a Component in JavaScript

JavaScript does not have a formal notion of classes. Nevertheless, JavaScript objects can
serve as classes using prototype based inheritance.

Class Definition

JavaScript classes are defined through their constructor functions. The template below
defines a constructor for ‘MyComponent’. The constructor accepts three arguments and
creates a div element to render its contents.
// Constructor
function MyComponent(arg1, arg2, arg3)
{
this._arg1 = arg1;
this._arg2 = arg2;
this._arg3 = arg3;

// Create a DOM element


var element = document.createElement('div');
element.id = "myComponent1";

// Important: Store the element Id to prevent circular references


this._elementId = element.id;

// Create a reference from the DOM element back to the object instance
element.myComponent = this;

// Register an event handler


element.onclick = MyComponent.onClick;
}

Note - It’s important to avoid circular references between the JavaScript objects and DOM
elements. Circular references of this type can cause memory leaks. In the constructor
above, circular references are avoided by storing the DOM element by id (as opposed to
storing the actual element).

Defining Methods

Methods should be created on the prototype object for the class. The prototype object is
automatically created for every JavaScript object. All instances of a class share a prototype
object. This makes it a convenient and efficient vehicle for defining methods on the class.
Within the method, the ‘this’ keyword can be used to reference instance specific data.

MyComponent.prototype.setSize = function(w, h)
{
var element = document.getElementById(this.elementId);
element.style.width = w + "px";
element.style.height = h + "px";
this._width = w;
this._height = h;
}

Static Methods

In some instances, it may be necessary to define a static method on the class. For example,
event handlers on a DOM element will require a static method. Static methods are defined
directly on the class as in the example below. Note that the ‘this’ keyword is not accessible
within the static method. So we store the instance object as a property on the DOM
element.

MyComponent.onClick = function(e)
{
var ev = getEvent(e); // Browser independent function to get the event
var element = getEventSrc(ev); // Browser independent function

var comp = element.myComponent;


comp.color = "red";
element.style.color = "red";
}

Instantiation

Instances of the class are created using the ‘new’ keyword.

var c = new MyComponent(arg1, arg2, arg3);

Pattern 2 - Singleton

The singleton pattern is used when a single instance of the component exists for the lifetime
of the application. Singletons are created using the same methodology as a regular
component. With two exceptions –

1. Singletons are constructed via a call to CreateInstance


2. All the methods on a singleton are static

// Static property to store the single object instance


var MySingleton.instance = null;

// Singleton constructor
MySingleton.CreateInstance = function()
{
if(MySingleton.instance == null)
{
MySingleton.instance = new MySingleton();
}
}

// Internal constructor
function MySingleton()
{
// Create an element
var element = document.createElement('div');
element.id = "mySingleton1";

this.elementId = element.id;
}

// Methods
MySingleton.setSize = function(w, h)
{
if(MySingleton.instance)
{
var element = document.getElementById(MySingleton.instance.elementId);
element.style.width = w + "px";
element.style.height = h + "px";
}
}

You might also like