JavaScript Tricks And Good Programming Style

Note that this is an updated version. Original version can be found here.

Thanks to the commenters I have updated this post with some better tricks.

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.

update
Michael Geary (his comment) pointed out this solution that I like.


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

The solutions mentioned (if (!optional), optional = optional || "default value", and the like) have problems when you pass 0 (zero) or null as an argument.

Commenters said that the 0/null problem is not one as this would not be the situation to use it. I would not say so. In an AJAX world where you do serialization back to a server/database often a 0/1 to false/true mapping has to be established. For default values it is important.

In case you just need to make sure that an object is not null I do prefer the mentioned

myobject = myobject || { animal: "dog" };

end update

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: update substitute variables with comments end update

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.

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 #

update
… should be avoided. Even if someone like Douglas Crockford (creator of JSON) uses it and calls it that.

Let me quote Jack Slocum who put it best:

// used to fix "this" prob with Function.apply to give call proper scope
// nice method to put in your lib
function delegate(instance, method) {
return function() {
return method.apply(instance, arguments);
}
}

function Animal(name) {
this.name = name;
this.hello = function() {
alert("hello " + this.name);
}
}

var dog = new Animal("Jake");
var button = {
onclick : delegate(dog, dog.hello)
};
button.onclick();

I removed my code as it can be considered obsolete by this.
end update

Reduce indentation amount #

update
I have removed the code because it leads people into believing something different than I meant. So let me put it differently:

What I am opposing is white space deserts. If you have many levels of indentation then probably something is wrong.

If a for loop only applies to a handful of cases, don't indent the whole loop in an if clause but rather catch the other cases at the top.
Often it is advisable to move longer functionality to a function (there is a good reason for that name) that you call throughout a loop.
end update

That's all for now, to be continued. Further readings on this blog:

update
Eventhough some commenters disagreed with what I said, I think posts like this are very much needed in the bloggersphere. Even if they are not free of errors on the first take, great people can help improve them. I would appreciate if more people took that risk.
end update

, ,

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.

, ,

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.

, , ,

Misuse of the Array Object in JavaScript

There is a very good post about Associative Arrays considered harmful by Andrew Dupont.

The title is a bit misleading but correct. When coming accross a piece of JavaScript like this
foo["test"] = 1;
there is nothing wrong about it. It's the basic usage scheme of assoziative arrays. Or should i rather say objects?

While in languages such as PHP arrays used like this $foo = array("test" => 1); is perfectly correct.

In JavaScript
var foo = new Array();
foo["test"] = 1;

works but does not do what you want.

I don't need to repeat Andrew's really great post, but basically you should use Object instead of Array.

var foo = new Object(); // same as var foo = {};
foo["test"] = 1; // same as foo.test = 1;

Now go and read Andrew's post.

via Erik Arvidsson.

btw: that post lead me to Object.prototype is verboten which explains for me why my for (i in myvar) {} loops never worked correctly. I was using prototype.js version < 1.4 (which messed with Object.prototype).

, , , ,

A better understanding of JavaScript

I've been working with JavaScript for years. It was my replacement for a server side language when I couldn't afford to buy web space in the mid-90's. Still, as the language becomes popular again, I recognized that I did understand the basics but there was much more to the language.

digg it, add to delicious

So I dug into the topic a little deeper. I can highly recommend reading the blogs of all the great JavaScript guys like Alex Russell (of Dojo), Aaron Boodman, Erik Arvidsson (both at Google), Douglas Crockford (at Yahoo). (Give me more in the comments ;)

So, JavaScript is easy to start with. You can take a procedural approach like in C. You declare a function, you call a function.

A Survey of the JavaScript Programming Language (by Douglas Crockford) does an amazing job at explaining the notable aspects of the language on a quite short page.

I want to point out the most interesting points for me:

Subscript and dot notation
You can access a member of an object by using two different notations:

var y = { p: 1 };
alert(y["p"]); // subscript notation
alert(y.p); // dot notation

The great difference is that with subscript notation you can also access member vars that contain reserved words (of which there quite a few in JavaScript). Dot notation is shorter and more convenient.

Different meanings of the this keyword
Consider this piece of code creating a small object.

click here
<script type="text/javascript">
var myobject = {
id: 'obj',
method: function() {
alert(this.id);
}
};
myobject.method();
var l = document.getElementById("link");
l.onclick = myobject.method;
</script>

When you call myobject.method();, this points to the current object and you receive an alert box with the text 'obj'. But there are exceptions:

If you call this function from within a HTML page via an onclick event, this is refers to the calling object (i.e. the link). You will therefore receive and alert box containing 'link' as message.

This can be useful in many cases, but if you want to access "your" object, you can't. Aaron Boodman proposed a function that was eventually named hitch:

function hitch(obj, meth) {
return function() { return obj[meth].apply(obj, arguments); }
}

You'd use it like this: l.onclick=hitch(myobject, 'method'); Now the this keyword points at the correct object.

You could also change the function to something like this and still use the previous notation:

method = function() {
if (this != myobject) { return myobject.method(arguments); }
alert(this.id);
}

Creating objects with new
I was always wondering how to create objects from a class as I am used to with other programming languages, which means that by instanciating the object is created according to the "building instructions" of a class.

Douglas shows this in more detail on his Private Members in JavaScript page.

I've quickly hacked together this example:

var x = function () {
var created = new Date();
this.when = function () { alert(created); }
}
var p, u = new x();
window.setTimeout("n()", 1000);
function n () {
p = new x();
p.when();
u.when();
alert(typeof p.created);
}

You receive 2 objects p and u that have different creation times. They also have a private variable created which is only accessible via the public function when (because specified via this).

So even as you create an object by using the new Object() or {} notation, you only receive a static object. If you want to instanciate it, you need to create it as function.

Closures
The example above already demonstrated closures. The fact that closures exist in JavaScript make it only possible to create private variables.

A closure is, to put it simply, a function within another function. The inner function has access to it's parents variables but not the other way round.

All together a function is just another data type that can be assigned to a variable. Therefore these two notations can be used interchangably:

function test() { alert(new Date()); }
var test = function() { alert(new Date()); }

The ominous prototype "object" is a way of using the this keyword from "outside".
Modifying the piece of code from before:

var x = function () {
var created = new Date();
}
x.prototype.when = function () { alert(created); }

But there's a pitfall. The created variable is private. Even though the function when now is a member of the object x it does not "see" the variable created. So in the original example the function when had privileged access (see Private Members in JavaScript).

Concluding
All in all I see that JavaScript is a powerful language. Many things that can be accomplished in an elegant (and sometimes quite unusual) way. (Curried JavaScript demonstrates even how to use it as a functional programming language)

I realize that there is a nice and clean solution for almost every problem you come across. This is where libraries come into play. The downside: you can quickly add tons of libraries, leading to large page sizes and memory consumption.

dojo for example is a really great library that provides you with numerous well thought-out functions, making your life a lot easier. But the size is 132 KB, just for the basic functions. More than a mega byte all in all. It circumvents needing to load everything by an in time loading mechanism (dojo.require).

In my opinion we'd need something like a local library storage. A Firefox extension would be a nice first step.
As far as I have looked into that topic, though, there are some difficulties. Foremost there is a problem with namespaces. Firefox clearly separates JS code by extensions from those coming from the web. A good thing, security-wise, but hindering in this case.

Maybe some Firefox guru can tell a way how to circumvent this, I think it might be worth a shot.

digg it, add to delicious

, , ,

Better code downloading with AJAX

I've been playing with Code downloading (or Javascript on Demand) a little more.

Michael Mahemoff pointed me at his great Ajaxpatterns in which he suggests a different solution:

if (self.uploadMessages) { // Already exists
return;
}
var head = document.getElementsByTagName("head")[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "upload.js";
head.appendChild(script);

Via DOM manipulation a new script tag is added to our document, loading the new script via the 'src' attribute. I have put a working example here. As you can see this does not even need to do an XmlHttpRequest (XHR later on) so it will also work on browsers not supporting that.

So why use this approach and not mine? Initially I thought that it was not as good as doing it via XHR because you receive a direct feedback (i.e. a function call) when the script has been loaded. This is per se not possible with this technique. But as in good ol' times a simple function call at the end of the script file will do the same job (compare source codes from the last example and this one (plus load.js)).

Using this method to load code later on also provides another "feature" (thanks for that hint to Erik Arvidsson): Unlike XHRs Firefox also provides a cache for scripts loaded that way. There seems to be a disagreement about whether this is a bug or a feature (people complaining that IE caches such requests while it could be quite useful in this scenario).

When using dynamically generated javascript code you will also have to keep your HTTP headers in mind (scripts don't send them by default). The headers Cache-Control and Last-Modified will do usually (see section 6.1.2 of my thesis)

The method above is also the method used by Dojo, a developer (David Schontzler) commented, too. He says that Dojo also only loads the stuff the programmer needs, so little overhead can be expected from this project.

Also Alex Russell from Dojo left a comment about bloated javascript libraries. He has some good points about script size to say (read for yourself), I just want quote the best point of his posting:

So yes, large libraries are a problem, but developers need some of the capabilities they provide. The best libraries, though, should make you only pay for what you use. Hopefully Dojo and JSAN will make this the defacto way of doing things.

So hang on for Dojo, they seem to be on a good way (coverage of Dojo to follow).

Finally I want to thank you all for your great and insightful comments!

, , , , ,

Code downloading with AJAX

Earlier, I suggested to use Code Downloading in order to reduce the size of AJAX application. I left the term undescribed, but I will change this now:

As JavaScript is an interpreted language, it is quite easy to load additional code, even after the application has "started". This means that only code absolutely necessary to display the app has to be loaded initially.

In the following example, we define a function test() in the context of an object App. Then via Ajax the original code is overwritten. Naturally also new functions can be loaded.



The downloaded code is eval'uated, i.e. it is executed. You cannot only execute statements but also define variables and functions.
Source of load.js:

App.test = function() {
alert("additional code loaded");
}

I have set up an example implementation of this.

This allows more flexibility for larger apps. My "negative" example, Kiko, could use this method to enormously reduce the amount of code to be loaded initially.

I alse see the possibility to only store encrypted Javascript source code on the server and decrypt it on-the-fly (of course also this would only prevent script kiddies from stealing, but it could challenge some hacker a bit more).

,

Documenting prototype.js for AJAX

As the prototype.js library lacks documentation and I recommend to use the down cut version for AJAX, I thought it might be useful to document how to use the AJAX related functions.

A "normal" AJAX callback

When you just want to do a post-back to the server (for example to store some data the user has just changed) you'd use the following piece of code:




A simple corresponding PHP script (store.php) would look like this:

< ?php if (!isset($_POST["value"])) { die("no value given!"); } $db = mysql_connect(); mysql_select_db("test"); mysql_query("INSERT INTO table (value) VALUES ('" + addslashes($_POST["value"]) + "')"); mysql_close(); echo "successful"; ?>

The value the user entered in the prompting box will be stored to a MySQL database. The magic happens in line 2 of the function store(): new Ajax.Request will do an HTTP POST to the given script at the first parameter (store.php) with the parameters given in the second argument. The yet unusual notations within curly brackets denotes a hash (also called associative array) that stores key/value pairs. Here the pair parameters (key) and '&value=' + value (value) are stored. Other possible key/parameter functions can be found at the preliminary documentation of prototype.js by Sergio Pereira.

This brings up a problem common to AJAX applications: you explicitly need to inform the user about what happened, or if it failed. This can be done via an Event handler. The most useful one might be onComplete. It is inserted like this:


function store() {
value = prompt("Give me a value, please.");
new Ajax.Request("store.php", {
parameters: '&value=' + value,
onComplete: function (req) {
if (req.responseText == "successful") {
alert("Your value has been stored successfully");
} else {
alert("Something went wrong when storing your value");
}
}
});
}

This will display an appropriate alert box depending a successful status message by the script. In near future I will describe how to use the Ajax.Updater feature which allows to easily modify your existing page to instantly display results of a query.

, , ,

prototype.js just for AJAX

As I stated earlier, the prototype.js library is too large for just using AJAX. In its current version (1.4.0_pre10) it weighs 36KB and contains lots of other features that are most probably not needed when just dealing with AJAX.

I have therefore created a smaller version just for AJAX, based on 1.4.0_pre10: pt.ajax.js 8.9K

It now has only a quarter of size and still provides some nice features such as $ as a wrapper of document.getElementById.

Creating this was not too difficult: it is merely a combination of 4 files that make up prototype.js:

Just do copy and paste into a new files, i.e. copying each file to the bottom of your new javascript file.

As you can see, you can easily create your own customized (smaller!) version of prototype.js to fit your needs.

, ,

Rise of slow AJAX applications

The current movement towards AJAX is a good thing. If it really were a movement towards AJAX. In my eyes it is rather a higher acceptance for Javascript applications. Of course, it is quite naturally in the early stages of a "hyped" technology to observe many misuses; they use AJAX just for the sake of using AJAX.

Pages get more voluminous because so much code has to be loaded to the browser (which makes the browser slow again) so you could just begin to use the application. This somehow reminds me of all the flash apps. Waiting for hours to load the page and you'll stick to that page for half a minute. (I do have a broadband connection. Still a page with 30kb loads 10 times faster than a 300kb page).

A negative example for this is Kiko, a web calendar. It has a nice "Kiko loading" box which already hints that they are doing something wrong. All Javascript files are included via server side scripting instead of loading them via <script src="xyz.js"> which would allow the browser to cache the file.

Kiko is just one example, there are others doing similar mistakes.

I think that the current usage of AJAX is a misuse of the browser. They are designed to render web pages (i.e. (X)HTML pages). Javascript is a bonus. Large data strucures can slow down browsers enourmously (they are still interpreting Javascript just in time).

As a conclusion I want to come up with some essential features for AJAX applications:

  • Keep it bookmarkable. Don't load everything to one page, let users return to a certain section of your app via their bookmarks.
  • Don't overuse AJAX. Often simple Javascript without server interaction will do. Try to reduce the server callbacks.
  • Minimize the code to be loaded. When you don't have any other choice, consider code downloading.
  • Speed up your apps with AJAX. Use AJAX for what it was meant for: tune your existing application at points where postbacks need to reload the same page with only little change.

, , , ,

Bloated Ajax Applications Due to Libraries

When Ajax began to rise, there was quite a movement towards the prototype javascript library. This was also pushed by the great Ruby on Rails. Then came the visual effects of script.aculo.us. They look great, they really do. But for what price? Lots of KB of code.

alex@www:~/scriptaculous/$ du *.js -ch --apparent-size
23K controls.js
18K dragdrop.js
21K effects.js
28K prototype.js
899 scriptaculous.js
12K unittest.js
8.7K util.js
109K total

This is unacceptable for just a library. Most of these KB's have to be downloaded and do not provide any functionality per-se. Broadband is not an argument here. To load or not to load 100kb is relevant.

I therefor really like the Sack of Ajax. It takes only about 4K:

alex@www:~/sack/$ du *.js -ch --apparent-size
3.9K tw-sack.js
3.9K total

Now this does not give us all the script.aculo.us stuff. For that case I suggest to just reuse the relevant parts of it. Just let the user download what you really use. Maybe one day we will see a reduced script.aculo.us. Or an alternative using Sack.

UPDATE: I now recommend to use protoype.js again, in a reduced version just for AJAX.

, , ,