5 JavaScript Techniques to Instantly Improve Your Code

JavaScript has quickly become an important language used in many aspects of website development. Although it may look very simple and straightforward to new programmers, it has several features and "gotchas" that may leave you scratching your head, wondering why your code doesn't work. This article will help you understand some of these ideas and explain how you can implement them to instantly improve your scripts.

Disclaimer: Although all these concepts apply to JavaScript itself, I will show some examples in jQuery to simplify the code used to demonstrate the concepts.  Feel free to use native JS or your own library of choice - jQuery is just my personal preference.  #5 discusses this topic further.

1. Keep your code safe with closures

Almost every website uses different scripts from different sources. By default, any function or variable created on the page is defined within the global "scope". This could become a serious problem if two scripts were using the same exact variable/function names, especially something common like "success"!

Instead of doing this, put your code inside a closure to ensure that no other script/library can accidentally mess around with your code:

(function(){
	// Your code goes inside here
	var incrementCount = function() {
		myButton.value = ++count;
	}

	var myButton = document.getElementById('clickme');
	var count = 0;

	myButton.onclick = incrementCount;
});

For more information on how this works, and to see some practical examples of this, check out my blog post about how closures work in JavaScript.

2. Use 'var' when declaring variables

JavaScript only has two different scopes for variables; they can be global or local. Variables declared outside of a function are always global. When a variable is declared inside a function, using the var keyword, it is scoped as a local variable and is inaccessible to other functions and outside code. However, if you neglect to declare a variable with 'var' it becomes global, regardless of where you defined it!

This recommendation is a lot like the previous one - while the code may work now, its possible that other scripts could inadvertently mess around with critical data/variables. I can tell you from experience that this can be a major headache to debug when suddenly things act up, so get in the practice of properly declaring your variables based on the desired scope.

3. Bind events once the DOM is ready

JavaScript is heavily event-driven. Most of the time, you'll want a function to run when a user clicks a button or changes text in a field. For example:

	$('#mybutton').bind('click', function(){
		alert('Hello World!');
	});

Dropping this script directly into a small test page may work. But if you wanted this to run on a larger page which takes longer to load (because of more HTML, images, JS, etc), it may try to bind the event before that button becomes available in the DOM.

The solution is to wait until the DOM is ready before binding the event. jQuery makes this simple:

$(document).ready(function(){
	$('#mybutton').bind('click', function(){
		alert('Hello World!');
	});
});

// Or, using the shorthand notation for document.ready:
$(function(){
	$('#mybutton').bind('click', function(){
		alert('Hello World!');
	});
});

By wrapping your code inside these lines, you can rest assured that it will only run once those target elements are ready and available in the DOM.

4. Harness event bubbling

When I first began serious work with JavaScript, I was unaware of how event bubbling worked. Essentially when certain events occur on an element in the DOM, they will bubble up to parent elements. Look at this code for example:

	$('#content').bind('contextmenu dragstart selectstart mousedown', function(e){
		if($(e.target).is('a, :input'))
			return true;
		else
		{
			e.preventDefault();
			return false;
		}
	});

That script is designed to prevent (or at least deter) the user from copying anything within the #content element. It doesn't matter what element inside #content they try to right-click or highlight with their mouse, because that event will always "bubble up" to #content which handles the event there. This is way more convenient than manually binding this function to every single element inside.

I remember one project where the old codebase had a table with thousands of rows, and each row had maybe 7 input boxes with hardcoded "onclick" events. When you have code like this, the browser must bind tens of thousands of events. This page took about a minute to fully load, used hundreds of MB of RAM, and usually caused the browser to crash. Our solution was to use jQuery to bind the function once to the table's "click" event. Anytime a user clicked on an input box, the event would bubble up to the TABLE element which could determine which input was clicked and proceed from there. It made the site much faster and reliable.

Events and bubbling does have a few 'gotchas' though, so I recommend further reading on how event bubbling works in different browsers.

5. Use native methods/attributes when possible

Wherever possible/feasible, try to use similar native methods/attributes instead of relying on your JavaScript library/framework as a crutch. All too often I come across JavaScript code that looks like this:

$('#sometextbox').change(function(){
   var contents = $(this).val();
});

While this is technically valid in jQuery and does what you'd expect, the same can be done with far less overhead:

$('#sometextbox').change(function(){
   var contents = this.value;
});

It looks similar but uses native DOM attributes to grab the value instead of invoking the jQuery object. With modern browsers, this optimization won't be noticeable to the end-user, but it's still a simple tweak that will cut down on overhead. Rule of thumb: if you can use native methods without sacrificing readability/maintainability, then do it. But if you are doing more complex things like AJAX requests or crazy-complex event bubbling, then use your JS library.