JavaScript Tricks And Good Programming Style – Original Version

Note that there is an updated version

I have been programming for about 10 years now, and I am always longing for improving my code. Throughout time I added a few habbits that I consider to be good practices and increase the quality of my code.

In a loose series I’d like to point out a few of them. As I am currently mostly programming in JavaScript, I will write most of my samples in that language; also some of the tricks I mention only apply to JavaScript. But most of them apply to most programming languages around.

Optional parameter and default value #
When defining a function in PHP you can declare optional parameters by giving them a default value (something like function myfunc($optional = "default value") {}).

In JavaScript it works a bit differently:

var myfunc = function(optional) {
if (typeof optional == "undefined") {
optional = "default value";
}
alert(optional);
}

This is a clean method to do it. Basically I pretty much recommend the use of typeof operator. Some people would do the above with a if (!optional), but my version works cross browser (e.g. Safari will throw an error when you try to negate null).

Parameters Hints #
The larger your app gets, the more functions you get which you would use throughout the app. It also creates a problem with maintenance. As each function can contain multiple arguments it is not unlikely that you forget what those parameters were for (especially for boolean variables) or mix up their sequence (I am especially gifted for that).

So what I do is this:

var myfunc2 = function(title, enable_notify) {
// [...]
}
myfunc2(title = "test", enable_notify = true);

This piece of code relies on the functionality of programming languages that the return value of an assignment is the assigned value. (This is something that you should also maintain in your app, for example with database storage calls, give the assignment value as a return value. It’s minimal effort and you might be glad at some point that you did it).

If you do this you can see at any point in the code, what parameters the function takes. Of course this is not always useful, but especially for functions with many parameters it gets very useful.

Also be careful that you would override the variable names in the scope of which you are calling the function. You might mini-namespace the variables, e.g. with letter+underscore (p_title, p_enable_notify).

Search JavaScript documentation #
When I need some documentation for JavaScript I use the mozilla development center (mdc). To quickly search for toLocaleString, I use Google: http://google.com/search?q=toLocaleString+mdc

As I am a German speaker I also use the excellent (though a bit out-dated) JavaScript section SelfHTML. I use the downloaded version on my own computer for even faster access.

The self variable #
This technique comes from Private Members in JavaScript by Douglas Crockford. By assigning a value in a function to this.value it will be publically accessible afterwards.

function Animal(name) {
this.name = name;
var self = this;
this.hello = function() {
alert("hello " + self.name);
//alert("hello " + this.name); // would fail
}
}
var dog = new Animal("Jake");
button = {
onclick = dog.hello;
}
button.onclick();

The cause of this problem is that the this keyword receives different values in different contexts. See here for a closer explanation.

Problem with this solution is that I am not absolutely sure if this creates a memory leak in internet explorer

Reduce indentation amount #
One of the most annoying things I find in other people’s code is this: (multiple) nested if clauses. Something like this:

var arr = ["dog", "cat"];
var action = 'greet';
for(i = 0, ln = arr.length; i < ln; i++) { animal = arr[i]; if (animal == "cat") { alert("hello " + animal); } }

This is only a short example, but I often saw this going deep into 10 levels of nested clauses. I suggest using the break and continue (and next in Perl):

var arr = ["dog", "cat"];
for(i = 0, ln = arr.length; i < ln; i++) { animal = arr[i]; if (animal != "cat") continue; alert("hello " + animal); }

This accomplishes the same with only one level of indentation. One more example for a function:

function greet_animal(animal) {
if (typeof animal == "undefined") return;
if (animal != "cat") return;
alert("hello " + animal);
}

Javascript is one of the few languages where you can leave the return value empty (i.e. typeof greet_animal() == "undefined"). You might want to rather use return false so that you can easily determine if the function failed for some reason.

javascript, tricks, coding practices

Firefox 1.5, XmlHttpRequest, req.responseXML and document.domain

Recently I have been working on a web application, extending it with an iframe on another subdomain.

When you set up communication with an iframe on another subdomain, it works by setting document.domain in both pages. Pretty nice and straight forward.
But it can mess up the rest of your page.

As soon as you have set document.domain you should be able to do an XHR to your original domain according to the same domain policy.

This will work in IE, Safari, and Opera.
This will not work in Firefox 1.0. This is very awkward but at least it has been fixed in 1.5.
So it will work in Firefox 1.5. But:

The responseXML object is useless. You can’t access it, you receive a Permission Denied when trying to access it’s content (e.g. documentElement). Very annoying.
Even stranger that responseText is still readable. What’s the reason for this? Is there some security risk i am unaware of or is it a plain bug?

As the responseText is available there is a pretty simple fix: re-parse the XML, which is kinda stupid and cpu intense if you have a lot of them. (something like: var doc =
(new DOMParser()).parseFromString(req.responseText, "text/xml");
)

I have some sample code available here.

Apparently a bug report has been filed at 1.5.0.1. No response from developers. Great.
Unfortunately it has only been filed for OSX, but it also afffects Windows Firefox.

Mozilla guys, fix this ASAP.

Update 2007-06-21: Things seem to start moving, we will likely have a fix for Firefox 3.

firefox bug, document.domain, XmlHttpRequest, responseXML