JavaScript Optimization

Here is a collection of tips to optimize Javascript coding. It is subject to change based on cross browser coding guidelines and personal coding standards. As in any programming language, use the following guidelines when optmizing Javascript:

1. Don’t waste time on premature optimization. Don’t apply a speed tweak that just makes your code uglier or needlessly complicated.

2. Don’t optimize blindly. Measure the speed of your code using a debugger or code execution timer before optimizing, and only optimize the code behind the bottleneck.

3. Don’t marry someone else’s code. Applying generic code and design patterns to create a solution you don’t understand is a pain. Unless you have time to learn the underlying
algorithm and weaknesses in the language that it fixes, cloned code can be a pain to customize and a nightmare to maintain over time.

4. Big libraries mean big bugs. Don’t assume libraries are risk-free, or that bug fixes
won’t break stuff. If you can spend time researching and comparing libraries to optimize your code, you can spend time learning their shortcomings and limitations as well. Remember, you or someone you know might have to fix a bug in a library one day.

5. Create complex data instead of complex logic. Simple variables are for simple operations; complex variables are for complex operations. If your code has too much logic, then reorganize your data. Assign long function calls to variables. Combine associated arrays into object literals. Convert tedious, repetitive loops into functions, and roll universal functions into prototypes of user defined objects.

Window Object

Use window.ActiveXObject to detect IE

Use window.ActiveXObject && window.XMLHttpRequest to detect IE >= 7

Use window.ActiveXObject && window.xdomainrequest to detect IE >= 8

Use window.xml.toString() && navigator.mimeTypes["image/svg+xml"] to detect Firefox <= 1.5

Use window.Iterator to detect Firefox >= 2

Use array.reduce to detect Firefox >= 3

Use window.opera.toString() === “[object Opera]” to detect Opera

Use var html = window.frames['iframe_name'].document.documentElement.innerHTML to get the contents of an iframe

Use “this” instead of “window” when referencing window functions or attributes in production code

Don’t use “this” when referencing user defined functions to avoid confusion and traps

Use location.replace instead of location.href to save memory and history entries

Use document.childNodes && !document.all && !navigator.taintEnabled && !navigator.accentColorName to detect Safari

Use window.devicePixelRatio to detect Safari >= 3

Use window.devicePixelRatio && !document.documentElement.style.textShadow to detect Google Chrome <= 0.3

Use window.open(’javascript:window.close();’,’_self’,’’); to close a tab

Navigator Object

Use parseFloat(navigator.appVersion) < 419.3 to detect Safari <= 2

Data Structures

A Closure is a child function defined within the scope of a parent function that inherits its parents local variables.

When called, arguments are passed to both functions in one call to the parent by appending
the child arguments after the parent arguments in the function call.

Delete closure variables after exiting functions to prevent memory leaks

Create an Object variable instead of a two dimensional array to simulate a hash.

Use a string literal to get the value of a hash key

ex.

var myObjectObject = {a:”alpha”, b:”beta”, “c”:”"}

myObjectObject["c"]

Group related variables into a hash to improve readability and object creation overhead

Use the ternary operator or a switch statement instead of an if…else block whenever appropriate

Use regular expressions instead of complex string manipulation whenever possible

Use boolean expressions instead of if statements to test for falsiness

ex.

X = [Y,Z][B] beats if (B) X=Y ; else X=Z

Cache all DOM nodes and nested properties in variables before accessing their data

Use Object.prototype.toString.apply(value) === ‘[object Array]‘ to perform type checking for arrays

Conditional Statements

Use “for (var i in hashName)” to loop through a hash and get or set each value

Only use for-in loops for object hashes where the index isn’t a sequential letter or number

Don’t use try-catch-finally inside performance-critical functions

Use hasownProperty in for-in loops to prevent the statement from checking any methods or properties that were inherited by the named object.

ex

for ( name in ob ) {
if ( ob.hasOwnProperty( name ) ) {

}
}

Use a break statement within the if block of a for loop to stop immediately after the condition is met and the value is used

Use the ”continue” statement to break out of an inner loop back into its outer loop

When writing a for loop, simply assign the value at each index to a variable during the iteration of the for statement instead of checking against the array length each time.

ex.

for( var i = 0, row; row = rows[i]; i++ ) {row.className = ‘newclass’;}) )

// Changes the element class

The first null or zero index value will return false and break the loop naturally without error, so make sure your array only contains non-null values.

This also works with while loops, such as when traversing the DOM until a node attribute is undefined

Also use the comma operator to cache the length of an array while initializing the counter of the for loop

(ex2.
for (var i = 0, len= wordList.length( ); i < len; i++)
{wordlist += ”,”;}
)

//Append commas to a list

If you have two loops in close proximity that use the same number of iterations (and don’t affect each other), you can combine them into one loop. So instead of this:

for (i=0; i<j; i++) {
sumserv += serv(i);
}

for (i=0; i<j; i++) {
prodfoo *= foo(i);
}

Do this:

for (i=0; i<j; i++) {
sumserv += serv(i);
prodfoo *= foo(i);
}

Fusing loops avoids the additional overhead of another loop control structure and is more compact.

Unrolling a loop reduces the cost of loop overhead by decreasing the number of times you check the loop condition. Essentially, loop unrolling increases the number of computations per iteration. To unroll a loop, you perform two or more of the same statements for each iteration, and increment the counter accordingly. So instead of this:
var iter = number_of_iterations;

for (var i=0;i<iter;i++) {
foo();
}

Do this:
var iter = multiple_of_number_of_unroll_statements;

for (var i=0;i<iter;) {
foo();i++;
foo();i++;
foo();i++;
foo();i++;
foo();i++;
foo();i++;
}

I’ve unrolled this loop six times, so the number of iterations must be a multiple of six. The effectiveness of loop unrolling depends on the number of operations per iteration. Again, the simpler, the better. For simple statements, loop unrolling in JavaScript can speed inner loops by as much as 50 to 65 percent.

Loop conditions and statements should be as simple as possible to minimize loop overhead. So instead of this:

for (var i=iter;i>0;i–)

Do this:

var i=iter-1;
do {} while (i–);

This technique simplifies the test condition from an inequality to a decrement, which also doubles as an exit condition once it reaches zero.

Move assignment statements, function calls, and conditional statements outside of loops and reference them as cached variables within the loop

Put the most likely true statements at the beginning of if…else branches

Use +1 instead of ++ in for loops

Variables and Built-in Functions

Assign “this” to a local variable to reference the parent function within a closure

Avoid using reserved words (Reference) such as ‘class’, ‘float’, ‘final’, ‘debugger’, ‘interface’, ‘package’, etc as variable names.

Assign default values to variables or only create them when storage is needed for a value

Cache frequently used function parameters in local variables

Use brackets around strings + variables:
[“string” + count]; instead of eval to loop over sequentially named variables

Use tag.className.match(“class”) to check the class of an element

Only concatenate two strings at a time to render faster and save memory

Use the blink tag instead of setTimeout to count seconds consistently across browsers

Use +var to convert a numeric string into an integer
ex. var a = “12″; var b = +a;

Use !!var to convert a variable to a boolean

Use string concatenation to convert an integer into a numeric string
ex. var a = 12; var b = “oceans ” + a;

Use indexOf() instead of a regexp test for simple strings

Use square bracket notation to reference node and property names that use reserved words or characters, such as getting form fields or setting form actions.

Cache math functions in variables before executing calculations within a loop

Instead of this:
var d=35;
for (var i=0; i<1000; i++) { y += Math.sin(d)*10; }

Do this:
var d=35;
var math_sind = Math.sin(d)*10;
for (var i=0; i<1000; i++) { y += math_sind; }

Style Object

Change the style.backgroundColor property instead of simply style.background to avoid overriding the default background image

Change the inline style attributes of an element by setting the style.cssText property to the selector/attribute pairs needed just like inline CSS

Change the class of an element dynamically by setting the className property to a relevant class value

Minimize the number of style changes made through the DOM by assigning classes to tags so that they can be changed using CSS instead

Event Object

Use the document object instead of the window object to attach onload events

Use DOMContentLoaded instead of load to add onload event listeners in non-IE browsers

Use the following code to enable onload event listeners for IE browsers:

(function()
        {
        try
          {
          // Try to scroll left to see if the document is loaded
          // This is a variation of the trick listed here:
          // http://www.hedgerwow.com/360/dhtml/ie-dom-ondocumentready.html
          // http://javascript.nwbox.com/IEContentLoaded/
          document.documentElement.doScroll("left");
          }
        catch( error )
          {
          // Call the function recursively until it scrolls
          setTimeout( arguments.callee, 0 );
          return;
          }
        // Call the onload event and pass the delegation function
        this.document.attachEvent("onload", handleEvent() )
        }
)();

Set onclick and other events to blank to destroy and disable event handlers for tags

For mouse events to swap images or colors, change classname instead of individual styles to keep presentation and code separate

Absolute or fixed positioned elements animate faster than relative or inline positioned

Use e.target to reference the element that triggered an event through the document root element

Redefine event listeners within conditional logic to override default actions

Remember to dereference DOM nodes passed into event handlers by some attribute

When calling setTimeout or setInterval recursively remember to set a boundary condition for the function call to exit

Use setTimeout to make sure events happen sequentially. The timeout between the first triggering of the function until the next will be the specified delay time plus the time taken to execute the function.

Use setInterval to make sure events fire at regular intervals regardless of execution time for prior calls. It is commonly used to set a delay for functions that are executed again and again, such as animations

When passing arguments to a function within a setTimeout or setInterval call, wrap it in an anonymous function, e.g. this.setTimeout(function(){myfunc(a,b,c)}, 100)

Never pass a simple or concatenated string as the first argument of a setTimeout or setInterval call. A string will be evaluated in exactly the same way as an eval call, including the associated performance impact. For this reason, pass an anonymous function or a callback instead

Reference user defined attributes instead of creating unneccesary classes and IDs to trigger events for specific elements

(ex. Popup Script using Custom Attribute)

Use keypress to identify alphanumeric keys and that have a unique ASCII value (A vs. a).

Use keyup/keydown to capture non-character key events, such as arrow keys, shift, alt, control, return, caps lock, etc.

For keypress, e.charCode || e.keyCode should work (Mozilla and Safari define e.charCode, while IE defines e.keyCode which returns the ASCII value).

For keyup/keydown, e.keyCode should work

Document Object

Check if JavaScript is available by checking DOM object retrieval and insertion
ex.
if(!document.getElementById || !document.createTextNode){ return; }

Always check the existence and nodeType of a DOM node before assigning its value to a variable or referencing it directly to avoid undefined or whitespace node access errors

Always assign the parent of any node you intend to change to a local variable, especially when changing attributes that are different across browsers
ex.
var element = this.document.getElementById(node);
var transparency = this.ActiveXObject ? element.filters.alpha : element.style;
transparency.opacity = this.ActiveXObject ? o_value : o_value/100;

Always specify an array index to focus on when using document.getElementsByTagName

Reference DOM nodes and attributes by index instead of by name to save processing time. So instead of this:

var form = document.f2; // refer to form by name

Do this:

var form = document.forms[1]; // refer to form by position

Use the action attribute to control the submission of a form

Always make sure the spelling of document.getElementById is singular, not plural

Use a space between class names to assign multiple classes to a tag

Use .parentNode.removeChild(this) to remove the current node

Use .value to get a tag’s value; use .nodeValue to set a tag’s value

Use .nodeName to get the tag name, and .nodeType to get the tag type

Use setAttribute(“id”,”value”) to set a tag’s id; use tag.id to get a tag’s id

In standards based browsers, getAttribute only works for attributes of the tag, not properties of the DOM element

Remove DOM node lists using removeChild() when performing loops and heavy modifications, then return them using appendChild()

Use createDocumentFragment to append a list of nodes to the page

ex.
var div = document.getElementsByTagName(“div”);

var fragment = document.createDocumentFragment();
for ( var e = 0; e < elems.length; e++ )
{
fragment.appendChild( elems[e] );
}
for ( var i = 0; i < div.length; i++ )
{
div[i].appendChild( fragment.cloneNode(true) );
}

Don’t assign anonymous Javascript functions to DOM nodes

Don’t assign large data structures to DOM attributes

Don’t assign a DOM node as a global attribute or variable value

When using createElement to add a node list or subtree, perform all loops and child node additions to the node before adding it to the document body

Always append child nodes to parent nodes instead of appending each to the document separately

Append tr and td tags to the tbody element instead of the table element directly

Destroy DOM events and delete DOM nodes stored in local variables after using them to clear memory

Use the visibility property instead of the display property to save memory

User one innerhtml statement instead of multiple appendChild statements in a loop when adding DOM nodes

Don’t use innerhtml to replace any elements that have events attached to them unless you reattach them

Use the current array index instead of a cached length value when traversing an active DOM node list. Remember to wrap the assignment in parentheses

ex.

Instead of this:

nl = document.getElementsByTagName(“P”);
for (var i = 0; i < nl.length; i++) { p = nl[i]; }

Do this:

for (var i = 0, p; (p = document.getElementsByTagName(“P”)[i]); i++)

Use cloneNode on a generic node instead of createElement when adding a node list using a loop

ex.

var ul = document.getElementById(“myUL”);
var li = document.createElement(“LI”);
var parent = ul.parentNode;

parent.removeChild(ul);

for (var i = 0; i < 200; i++) { ul.appendChild(li.cloneNode(true)); }

parent.appendChild(ul);

Use hasAttribute instead of getAttribute to check against null attributes

Loop through childNodes() array rather the starting from firstChild() and lastChild() and individually checking previousSibling and nextSibling

Use hasChildNodes() rather than childNodes.length > 0 to check the existence of children

Use document.getElementsByTagName(aTag).item(0) != null instead of document.getElementsByTagName(aTag).length > 0 to check for the existence of a tag

Use a library function to replace all IE or Netscape document.layers or document.all references in legacy code with W3C DOM code, such as:

function getElement(aID)
  {
  return (document.getElementById) ? document.getElementById(aID) : document.all[aID];
   }

Use getElementsByTagName() to replace global namespace polluting caused by accessing an element through document.elementName or the element’s name in legacy code

document fragments, which are lightweight documents that contain a subset of a normal document’s interfaces. For example, getElementById does not exist, but appendChild does. You can also easily add document fragments to existing documents.

document.createDocumentFragment(), returns an empty document fragment in standards based browsers, but returns a regular document in IE

Use document.ownerDocument to return the document object containing the current node.

Use textContent in standards browsers and innerText in IE to set the text value of a node

Only use document.write to add on demand CSS links that require Javascript

ex.
var W3CDOM = (document.getElementsByTagName && document.createElement);

if (W3CDOM){document.write(”);}

Use IFrameElm.contentDocument in standards based browsers and document.frames["name"] in IE to access an iframe’s document object

designMode turns an HTML document into a rich text editor field. Once turned into the editor, commands can run on the document through the execCommand command. Standards based browsers don’t support contentEditable attribute in IE for making any widget editable, but you can use an iframe to add a rich text editor. The rich text editor creates HTML with inline CSS styles for the generated markup in standards based browsers, and allows you to toggle between HTML and CSS mode by toggling the useCSS execCommand between true and false, but IE always generates HTML markup with deprecated tags.

Put all single instance form input into an array with one index so both input fields, radio buttons, and checkboxes can be validated with the same code

ex.

if (typeof someElement.length == “undefined”)
{
someElement = [ someElement ];
}

for (var i = 0; i < someElement.length; i++)
{
// handle multiple instances
}

AJAX Functions

Use xmlhttp.open(‘GET’, file?param1=x&param2=y, true); to initialize an AJAX GET request with parameters in the URL.

Use send(null) afterwards to process the request without POST data

Use xmlhttp.open(‘POST’, file, false); to initialize an AJAX POST request with parameters in the send function, as in xmlHttp.send(“param1=x&param2=y”);

Use xmlHttp.onreadystatechange = function(){…} to check the status of an AJAX request

Use if (xmlhttp.readyState= =4 || xmlHttp.readyState= =”complete”) to check if an AJAX request is ready to return data

Use if (xmlhttp.status= = 404) to check if a page does not exist

Use xmlhttp.setRequestHeader to add headers to identify the data that is sent, such as a

Content-Type as form(application/x-www-form-urlencoded) or XML(text/xml) data

The POST method is required when sending data, GET method is for receiving data. For security purposes, always use POST for both sending and receiving data

Use false as the async parameter for a POST and true as the async parameter for a GET to allow the browser to continue while getting information, but pause while sending information

Use xmlhttp.getAllResponseHeaders() to get CGI headers from a requested page

Use xmlhttp.responseText to get plain text from an AJAX request and insert it using
innerHtml

Use response = xmlhttp.responseXML.documentElement to create a DOM tree from an XML response

Use response.getElementsByTagName to parse XML data from an AJAX call

Use xmlhttp.send() to send the AJAX request and input parameters

Use xmlhttp.close() to close the request and exit

Do not send an information using AJAX that you don’t want to be seen in the URL or headers, such as login information

User Defined Functions

Use closures for functions that return arrays so you can loop through the array directly

Use namespaces for all functions to prevent naming conflicts
ex.

var Singleton = function()
{
var privateValue = “private value”;
return
{
prop: “value”,
method: function()
{
alert(privateValue);
}
};
}
();

Define a functions or variable using object literal notation to access its values from outside of its own scope.
var myObject =
{
z : 2 ,
myNestedObject : { z : 8 }
};

alert(myObject.z) //alerts 2
alert(myObject.myNestedObject.z) //alerts 8
Encapsulate all functions within an anonymous function to prevent access to the global scope

ex

(function () {

/*
Define here the variables and functions of the module.
Use your namespace object to access the DOM, handle events
*/

})();

Generalize all functions that modify the DOM(form validation, style changes, event handling, )

Browser Differences

In addition to the standard getFullYear() function, IE supports the deprecated getYear() function to return four digit dates
An extra comma at the end of an object member list will cause an error in IE
ex.
obj = {
name:’Troy’,
color:’Green’,
‘class’:”Physics”,
};

In IE, a semicolon between and if block and an else block will not trigger an error or conditional bug

In IE, an onchange event handler on an input element will not trigger until a subsequent event is added to the queue

In IE, the Error object lacks the name property and message property

IE does not support the javascript reserved keyword const used to define constants

DOM nodetype constants(document.body.DOCUMENT_NODE, document.body.ELEMENT_NODE, etc) are undefined in IE

In IE, a try..catch..finally block needs to be nested within a dummy try…finally block to work properly

The number.toFixed() function is broken in IE

IE does not support the type=”application/ecmascript” and type=”application/javascript” property values of the script tag

In IE, button.value returns the inner text of a button instead of its value

In IE, the InsertRow() function is broken

IE does not properly evaluate the objOption.defaultSelected = true statement

The offsetLeft, offsetTop and offsetParent attributes are broken in IE

The offsetHeight attribute is wrong for a div created dynamically using document.write in IE

In IE, the document.firstChild.tagName, document.firstChild.nodeName, and document.doctype attributes are broken

The NAME attribute cannot be set at run time on elements dynamically created with the createElement method in IE

DOM generated form fields cannot be referenced by name or array subscript in IE

The hasAttributes method is not supported in IE

IE does not support the Attributes object of attribute nodes

The id attribute is used by the USEMAP property to reference a MAP tag instead of the name attribute in IE

The value of document.domain cannot be changed after being defined in IE

When you set the innerHTML property of the Select object in IE, the first option tag is truncated. Set the innerHTML of a new option tag instead

In IE, cloneNode() and removeChild() do not remember any DOM changes to the referenced elements

The navigator.plugins and navigator.mimetypes collections are not populated in IE

Opera doesn’t set event.x and event.y correctly

Opera uses an array instead of an object as the data structure to store the arguments of a function

IE does not support the cssFloat property

Firefox supports the __proto__ object

IE defines an window object constructor as [object] instead of [object HTMLDocument]

IE defines global functions as objects instead of as functions

ex. typeof(window.alert) is an function in all browsers except IE

IE allows variables which catch exceptions to exist outside the scope of the catch function

In IE the global object __global__ does not inherit from Object.prototype

IE incorrectly implements the delete operator when applied to the global object

IE incorrectly allows namespaced functions to be referenced globally

IE incorrectly allows function calls before function definitions if both are in the same scope

IE does not default the separator of the join() function to a comma if its value is undefined

IE does not default the value of the toPrecision() function to toString if a range is undefined

IE returns “undefined” as the value of the unshift() function call

IE returns zero instead of NaN when the valueOf() function is called directly

IE returns an empty string instead of undefined for any capturing parentheses skipped by | in a regexp pattern

ex.
var a = /((a)|(ab))((c)|(bc))/.exec(‘abc’);
document.write(a);

IE does not throw either the SyntaxError or the TypeError exceptions for regular expressions

IE does not support indirect calls to eval using a cached variable

The following properties are all broken in IE:
Object.length
String.fromCharCode.length
String.indexOf.length
String.lastIndexOf.length

IE ignores the capturing parentheses of the regexp in the split function

The event handler in IE doesn’t set this to the calling element, so you must pass it into the function to reference it

When retrieving a style attribute, IE returns a style object, rather than an attribute value.

When retrieving an event-handling attribute such as onclick, IE returns the contents of the event handler wrapped in an anonymous function instead of a string.

When retrieving an attribute value which evaluates to boolean true (such as disabled or checked, when defined), IE returns a boolean instead of a string.

When retrieving a value that evaluates to a number (such as tabindex), it returns a number instead of a string.

IE returns null for non-defined attributes it doesn’t recognise (ie. custom attribute names).

IE returns different values when using the getAttribute function instead of dot notation when accessing DOM property values in many cases. Use getAttributeNode() instead.

IE7 cannot set a cookie if the domain name is in uppercase characters and it has an odd number of characters. The initial dot after www is not included in the number of characters. For example, if the cookie tries to set the .EUROPE.CORP.CONTOSO.COM domain name, the cookie cannot be set. This domain name has 23 characters.

IE6 may crash when the JScript garbage collector runs and you have dynamically removed a TBODY, THEAD, or TFOOT HTML tag from a table in Windows XP. This problem occurs because the garbager collector cleans up the internal references to the TBODY, THEAD, and TFOOT elements when the garbage collector runs. By doing this, the garbage collector deletes the internal objects even though other references to those objects still exist. When those objects are used later, certain operations may overwrite memory. This happens in unpatched(MSKB918961) versions of IE6.

Custom properties that overload standard Object properties like toString are not enumerated using for-in in IE. Consequently, using for-in to copy that property from one prototype to another object is not possible

Since IE doesn’t support mutation events, it doesn’t reflow the document’s layout in many situations where it’s strongly needed, such as inserting an element or updating an attribute. Reactivating the node by assigning the node to itself is a workaround in some situations.

When updating properties of ’style’ of a :before/:after rule, the generated content on which this rule apply is not updated. It keeps the old value of the property. To make clear, we have xx:before { content: ‘A’; color: red; }, and we change the color property value to ‘green’, but the generated content still use the ‘red’ value until we deactivate then reactivate the rule using the Dev Tools.

Math Functions

If the evaluation of an expression is costly, replace it with a less-expensive operation. Assuming that a is greater than 0, instead of this:

a > Math.sqrt(b);

Do this:

a*a > b;

Or even better:

var c = a*a;
c>b;

Instead of calling expensive functions to generate a limited set of known values, you can store the hardcoded calculations and reference the results. So rather than this:

function foo(i) { if (i < 10) {return i * i – i;} }

Do this:

values = [0*0-0, 1*1-1, 2*2-2, ..., 9*9-9];

function foo(i) { if (i < 10) {return values[i];} }
You can use a bitwise operation instead of a mod function to test whether a number is odd or even. For example, do:

ex.

if (flipflop & 1) // If flipflop is odd

instead of:

if (flipflop % 2) // If flipflop is odd

You can substitute math.floor with a bitwise operation which may run faster:

Math.floor(n) == (n&0xFFFFFFFF) == (n<<1) == (n|0)

You can convert hex colors to their rgb values using bitwise operations

ex.

// We want to know the red, green and blue values of this color :
var color = “#FEA946″ ;
var red = color >> 16 ;
var green = (color & 0×00FF00) >> 8 ;
var blue = color & 0×0000FF ;

alert(‘Red : ‘ + red + ‘, Green : ‘ + green + ‘, Blue : ‘ + blue) ;

// Will display…
// Red : FE (254), Green : A9 (169), Blue : 46 (70)

You can work with number that are a power of 2 (a multiple of 2,4, 8, etc.) using with bitwise shorthand
ex.

(x = y % 32) == (x = y &31)
(x = y * 8) == (x = y <<3;)

You can do more concise and readable Boolean comparison
ex.

Instead of:
if( a==b && c==d && e==f )

Do:
if( ( (a-b) | (c-d) | (e-f) ) == 0 )

ex 2.

Instead of:
if( (x==2) || (x==3) || (x==5) || (x==7) || (x==11) || (x==13) || (x==17) || (x==19) )

Do:
if( (1<<x) & ( (1<<2)|(1<<3)|(1<<5)|(1<<7)|(1<<11)|(1<<13)|(1<<17)|(1<<19) ) )

You can swap two variables by using a bitwise xor,^, instead of a temporary variable
Usually, when not using ^, you will do:

temp = a;
a = b;
b = temp;

Using ^, no “temp” is needed:

a ^= b;
b ^= a;
a ^= b;

Writing bitwise XOR without ^
Suppose you wanted to implement bitwise XOR, but didn’t have ^ operator. What would you do? With bitwise AND (&) and bitwise OR (|), you can do this.

var bitwise_or = function(x,y) { x ^ y == (~x & y) | (x & ~y) }

Source Code Compression/Obfuscation

Use .htaccess to prevent read access to JS, CSS, and XML files

Use .htaccess and server side scripting to minimize JS files dynamically
Example .htaccess Rule:
# Send all JS file requests to the minimize script
RewriteRule ^js/(.*).js$ /js/minimize.php?jsPage=$1 [L]
Example PHP script using JSMIN
<?php
require(’../includes/jsmin.php‘);
// Output a minified version of the Javascript file.
echo JSMin::minify(file_get_contents($_GET[’jsPage’] . ‘.js’));
?>

Bandwidth/Latency

Use callback functions to filter each row of data as it is processed instead of using redundant for loops through the same array

Use memoization to cache all function results

Use a single array join instead of multiple string concatenations

Use getElementsBySelector over getElementsByClassName

Keep if statements outside of functions and loops

Outsource RSS feeds to feedburner and images to Photobucket or S3

Add this rule to your .htaccess file to compress all text files:
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript text/css application/x-javascript

Cache dynamic images and text in hidden divs when initially loading a page instead of calling AJAX repeatedly

Place javascript tags at the end of the body tag to defer loading until the page is rendered

Use on demand script calls (dynamic script insertion) instead of putting multiple script tags in the document head tag that may not be needed

Put javascript files on a subdomain to preserve bandwidth

Use on-demand javascript calls to conditionally load scripts as needed

ex.
var script = document.createElement(“script”); script.src = ‘test.js’; script.type = ‘text/javascript’;
document.body.appendChild(script);

Use event delegation instead of scattered onload, onclick, and onmouseover events

Debugging

Use typeof to check the data type of variables when comparisons always fail
Use in to check to inheritance of objects when function calls fail
Prepopulate quotes, brackets, or parenthesis in functions before entering text
Check the existence of object functions or attributes before using them

Accessibility

Define hrefs for AJAX links that pass the javascript parameters to an alternative HTML only page

Always add return false to event handlers so that links and form submissions work if JavaScript is disabled

References

JavaScript Toolbox

Rediscovering JavaScript

JavaScript Magic Properties: __proto__ __count__ __parent

JavaScript Functional Programming

JavaScript Scope and Prototype Chains

JavaScript Programming Patterns

Migrate Apps from IE to Mozilla

Rules of Unobtrusive JavaScript

Efficient JavaScript

Client Side Performance Optimization of JavaScript

JSLint JavaScript Recommendations

Programming Conventions of the JavaScript Language

JavaScript Performance Tuning Reference

JavaScript Performance Tests

Conditional Statement Shorthand in JavaScript

Detecting HTML5 Features

Associative Arrays Considered Harmful

Browser Feature Detection

Common Feature Tests among Browsers

Common Regexp Patterns

Important Facts About JavaScript and Related Technologies

Help on understanding Bitwise Operations

Example Use of Bitwise Operators

Discussion of Practical Bitwise Applications on the official PHP site

Using bit masks for access control

Bitwise XOR Encryption

Closure Tutorial

Object Data Tutorial

With() Method Tutorial

Arguments.callee Tutorial

Anonymous Recursion Tutorial

Singleton Tutorial

Namespace Tutorial

Boot Camp JavaScript

JavaScript Cheat Notes

1 Comment »

RSS feed for comments on this post. TrackBack URI

  1. “Use the blink tag instead of setTimeout to count seconds consistently across browsers”

    Is this a sly reference to the 2007 April Fools joke on Ajaxian?

    http://ajaxian.com/archives/the-new-timers


Leave a comment

You must be logged in to post a comment.

Blog at WordPress.com. | Theme: Pool by Borja Fernandez.
Entries and comments feeds.