Christian Heilmann

Posts Tagged ‘syntax’

JavaScript shortcut notations that shouldn’t be black magic to the “average developer”

Tuesday, November 27th, 2007

When publishing articles about JavaScript development you run into many rules set by publishers and editors. This is a great thing as it keeps us authors on our toes and makes us understand more about how much work successful publishing really is. However, it can also be terribly annoying, especially when older idioms just stick. One of them is that “the average developer” does not quite understand JavaScript shortcut notations.

Now, if you are “the average developer”, please give me 5 minutes of your time to get through the following, you’ll understand a lot more code out there and also spend a lot less time writing your own scripts.

Array shortcut notation – It is hip to be square

The first bugbear I have are arrays. These are terribly useful and omnipresent in JavaScript and still I find people who write convoluted things like:

var links = new Array();
links[0] = 'http://cuteoverload.com';
links[1] = 'http://icanhascheezburger.com';
links[2] = 'http://pencilsatdawn.wordpress.com';
links[3] = 'http://apelad.blogspot.com';
// ... ad nauseam ...

This is convoluted (you have to repeat the array name for every item) and also tricky to maintain. When you change the order (granted the order is of importance) you need to change the number, too. It is not necessary, as the numbering is done automatically for you. All you need to do is use the square brackets:

var links = [
  'http://cuteoverload.com',
  'http://icanhascheezburger.com',
  'http://pencilsatdawn.wordpress.com',
  'http://apelad.blogspot.com' // <-- last one, NO COMMA!
];

This makes it more obvious from a visual point of view, too. The indentation makes it easy to spy where the array begins and where it ends. Much less line noise to take in.

Notice that you need to separate each item with a comma, but make sure you don’t have a trailing comma at the last item. You can even nest arrays that way:

var links = [
  'http://cuteoverload.com',
  'http://icanhascheezburger.com',
  [100,200,20,'foo'],
  'http://pencilsatdawn.wordpress.com',
  'http://apelad.blogspot.com' // <-- last one, NO COMMA!
];

On that note, here’s another trick: to add a new item to arrays, you can either use the push() method or use the length property:

links.push('http://dailypuppy.com');
links[links.length] = 'http://bigeyedeer.wordpress.com';

Associative Arrays – OMG! Ponies!

One myth that keeps sticking is that JavaScript has a magical thing called associative arrays. These allow you to not just number the items but give them names instead! You find examples like:

var links = new Array();
links['Cute Overload'] = 'http://cuteoverload.com';
links['I can has cheeseburger'] = 'http://icanhascheezburger.com';
links['Pencils at dawn'] = 'http://pencilsatdawn.wordpress.com';
links['Hobotopia'] = 'http://apelad.blogspot.com';

This is treachery to the highest degree. It is a confusing JavaScript trait, as what you created here is not really an array, but an object. Want proof? – Do an alert(typeof links) or try alert(links[1]).

Object shortcut (literal) notation – getting curly.

So called associative arrays are actually objects, which means you will also find other scripts that took the earlier example serious and use the following instead:

var links = new Object();
links['Cute Overload'] = 'http://cuteoverload.com';
links['I can has cheeseburger'] = 'http://icanhascheezburger.com';
links['Pencils at dawn'] = 'http://pencilsatdawn.wordpress.com';
links['Hobotopia'] = 'http://apelad.blogspot.com';

Again we have far too much repetition. For objects, you have the Object Literal Notation as a shortcut, which basically is using curly braces:

var links = {
  'Cute Overload' : 'http://cuteoverload.com',
  'I can has cheeseburger' : 'http://icanhascheezburger.com',
  'Pencils at dawn' : 'http://pencilsatdawn.wordpress.com',
  'Hobotopia' : 'http://apelad.blogspot.com' // <-- again, no comma!
}

The semicolons get replaced by commatacommas (Happy, Stuart?) (except for the last one which you need to omit) and the equal signs become colons. If the properties (the things to the left of the colon) don’t have any spaces in them, you can even get rid of the quotes:

var chris = {
  hair : 'red',
  age : 32,
  city : 'London'
}

You can access the properties with object.property when they don’t have any spaces or with object[property] when they have spaces. For example:

var links = {
  'Cute Overload' : 'http://cuteoverload.com',
  'I can has cheeseburger' : 'http://icanhascheezburger.com',
  'Pencils at dawn' : 'http://pencilsatdawn.wordpress.com',
  'Hobotopia' : 'http://apelad.blogspot.com' // <-- again, no comma!
};
alert(links['I can has cheeseburger']);
alert(links.Hobotopia);

Simple if-else statements – ask and define with the ternary notation

You can shorten simple if statements dramatically. With simple I mean an if statement that assigns one of two values like this:

  var YUIguy;
  if(city === 'London'){
    YUIguy = 'Chris';
  } else {
    YUIguy = 'Eric';
  };

Again, a lot of repetition there. The ternary notation works around that problem:

var YUIguy = city === 'London' ? 'Chris' : 'Eric';

A lot of equal signs there. Maybe some parenthesis will make it clearer:

var YUIguy = (city === 'London') ? 'Chris' : 'Eric';

What’s going on here? You define the variable YUIguy and assign it a value. Then you have a statement, in this case the comparison of the variable city and if it equals to the string London (=== tests for both the value and the type, much safer than ==).

Then you ask the question if that is true or not by using the question mark. The option on the left of the colon is the answer to the question when the condition was met and the option on the right of the colon is the answer when the condition was not met. Any condition that could be true or false can go inside the parenthesis.

var direction = (x < max) ? 'left' : 'right';

Offering a fallback option with the default operator

The last thing I wanted to quickly talk about is the double pipe (||) default operator. This one is terribly useful when you want to make sure that something is set with a default value. The following construct is something that should not show up any longer:

  var section = document.getElementById('special');
  if(!section){
    section = document.getElementById('main');
  }

Again, useless repetition, as the same can be written as:

  var section = document.getElementById('special') || document.getElementById('main');

If the first is not defined, the second gets assigned as a value to section.

Thanks for your time!

I hope this helped “the average developer” to understand how you can make your JS a lot shorter without really cutting down on readability. If you want more detailed information about all these goodies, check out Douglas Crockford’s articles on the matter:

Sending objects as parameters – good or bad?

Wednesday, November 7th, 2007

One of the differences I keep seeing in functions and methods lately is that people seem to go away from the strict pattern of expecting parameters in a certain form. If you look back some years you might remember functions like the following:


function doLayerFloat(id,start,end,direction,speed,fade,whatelse,Iforgot){
...
}

This, at least to me is rather annoying as I am terrible at remembering the order the parameters need to be sent in (conditioning in PHP confusion probably). The other issue I kept seeing with this was that if you didn’t want to provide some of the parameters but one of the last ones you had to send empty strings or even null values:


doLayerFloat(‘myDIV’,0,30,null,null,true,null,null){
...
}

// or
doLayerFloat(‘myDIV’,0,30,’‘,’‘,’‘,’‘,’‘){
...
}

This is both confusing and convoluted. Other scripts I have seen work around the issue by using the arguments array, which at least allows a flexible amount of arguments to be sent.


function doLayerFloat(id){
var args = arguments;
for(var i = 1; i < args.length; i++) {
...
}

}

However, my favourite these days is functions that actually take a few defined parameters (or a single one), allow for it to be several things and allow you to send an object as the properties:


function doLayerFloat(id, props){
var elm = typeof id !== ‘string’ ? id : document.getElementById(id);
for (var i in props){
...
}

}

This allows the id to be either an element reference or a string and takes an object as the second parameter in which I can define the order and amount any which way I like (provided the method then tests for each of them and their correct values):


doLayerFloat(‘x’,{start:20,end:30,fade:true});
// or
doLayerFloat(myElm,{fade:true,direction:’right’});

This also allows you to define default values should the properties not be set, something you can do in PHP but not in JavaScript. In PHP, this works:


function foo($bar=2,$baz=’foo’){
}

In JavaScript that can’t be done, but if you use an object you can predefine if the properties are not set:


function doLayerFloat(id, props){
var elm = typeof id !== ‘string’ ? id : document.getElementById(id);
props = props || {};
props.start = props.start || 100;
props.fade = props.fade || false;
}

Do you agree? Or is the object literal syntax still too tricky?