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

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 <notextile>===</notextile> 'London'){
    YUIguy = 'Chris';
  } else {
    YUIguy = 'Eric';
  };

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


var YUIguy = city <notextile>===</notextile> 'London' ? 'Chris' : 'Eric';

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


var YUIguy = (city <notextile>===</notextile> '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:

Tags: , , , , , , , , ,

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

  1. Wally Punsapy Says:

    i’m too lazy to do it myself. can you:

    var section = $(’special’) || $(’main’) || $(’submain’) | $(’ternarymain’);

    if, else if, else if, else …. ?

  2. ragaskar Says:

    great article!

    i find these sort of operator ‘tricks’ that save typing time and, in many instances, clarify code, can be quite difficult to search for using google, so it’s nice to have a little guide to them all wrapped up.

    Thanks also for clearing up the array/hash differences — not coming from the js world, the exact differences involved were previously a bit of a mystery for me.

  3. sil Says:

    Nice work. Although the plural of “comma” is “commas”, despite how it was originally derived from ancient Greek :)

  4. Robert Nyman Says:

    Great! I think these are common pitfalls to people who aren’t very experienced with JavaScript, so it’s good to have them easy and properly explained.

  5. Eric Miraglia Says:

    It’s YUIdude, actually…

  6. Clive Murray Says:

    Nice one, Herr Heilmann. Quick question (I could look it up, but why do that when I have a JS Guru available to answer questions? ;-) ):

    Where I might previously have used the following to append items to an array:

    var myArray = new Array();
    myArray[myArray.length] = “something”;
    myArray[myArray.length] = “something else”;
    myArray[myArray.length] = “something else again”;

    What would be the shortcut square-brackety version of appending a new item? Or multiple items at once?

    Cheers,
    –clive.

  7. Menno van Slooten Says:

    Nice lineup. You wrote “The last thing I wanted to quickly talk about is the double pipe (||) default operator.” Actually, the || operator is just a logical OR operator that has some unusual behavior in JavaScript. The Mozilla documentation describes it as such:

    “expr1 || expr2 : Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true; if both are false, returns false.”
    http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Logical_Operators

    The same goes for the && AND operator, btw, which returns expr1 if it evaluates to false and expr2 if it evaluates to false.

  8. Caz Mockett Says:

    Thanks Chris,
    You’ve helped this below average (JS) developer pull herself up by the bootstraps a little! ;-)

  9. cypher Says:

    This “JSON” notation.
    Nothing more.

  10. Viktor Says:

    Just be sure if you are using a library with a dollar function e.g. $(’#foo’) (e.g.jQuery)

    that the library handles IE’s buggy implementation of getElementById() otherwise you will be in for a shocker when all of a sudden, some pages on your site/application don’t work in IE. :-(

    Bug reference:
    http://webbugtrack.blogspot.com/2007/08/bug-152-getelementbyid-returns.html

  11. Milo Says:

    Calling it a “default operator” is misleading. There’s nothing special about the “||” operator when used in such a context. The “||” operator is simply a logical “or” operator that is extended to work with non-boolean datatypes. If the left-hand operand resolves to “true” then it is returned, otherwise the right-hand operand is returned. This is exactly the same as the “or” operator in any other language.

  12. Anthony Ettinger Says:

    Excellent synopsis of good coding practices.

  13. Liam Clancy (metafeather) Says:

    Another note on the double pipe operator – you have to be careful what functions/values/variable you are testing against.

    The examples given are very common but the effect on ’section’ can vary slightly depending on the statements being assigned and this should be noted if you use the value in a boolean test, or are re-factoring existing code.

    The example ‘!section’ test is relying on ‘null’ and ‘undefined’ evaluating to ‘false’, or as Crockford describes it objects being ‘truthy’.

    However this does not allow you to distinguish between an explicit ‘false’ and ‘undefined’.

    typeof section;
    >>> undefined
    var section;
    typeof section;
    >>> undefined
    var section = false;
    typeof section;
    >>> boolean
    // neither element exists
    var section = document.getElementById(’special’) || document.getElementById(’main’);
    typeof section
    >>> object

  14. iljmez Says:

    I have a question:
    How would one go to iterate through this array (object):
    var chris = {
    hair : ‘red’,
    age : 32,
    city : ‘London’
    friends : [{
    fred: {[hair: 'black',age:35,city:'London']},
    steeve: {[hair: 'brown',age:31,city:'London']},
    }]
    }

  15. Chris Says:

    @iljmez, what’s with all the arrays?

    
    var chris = {
      hair : 'red',
      age : 32,
      city : 'London',
      friends : {
        fred:{
          hair: 'black',
          age:35,
          city:'London'
        },
        steeve: {
          hair: 'brown',
          age:31,
          city:'London'
        }
      }
    };
    function loopproperties(o){
        for(i in o){
            console.log(i+':');
            if(typeof o[i]!== 'object'){
                console.log(o[i]);
            } else {
                loopproperties(o[i]);
            }
        }
    };
    
  16. Fred Polgardy Says:

    “You can access the properties with object.property when they donât have any spaces or with object[property] when they have spaces.”

    Not quite. The key has to be a valid identifier to be used in a hash literal without quotes, not just have no spaces. You couldn’t say:

    var foo = {
    whats.up : ‘asdf’
    };

    You’d still have to quote the ‘whats.up’.

    But that’s a minor quibble. Good post!

  17. Bill Says:

    These are great tips. The funny thing is that I learned to use them in Javascript AFTER using them in Actionscript (Flash) because AS and JS both use the ECMAScript standard.

  18. reza Says:

    Wally,

    I didn’t understand the last single pipe ‘|’ in your statement!?

    >var section = $(âspecialâ) || $(âmainâ) || $(âsubmainâ) | $(âternarymainâ);

  19. Wade Says:

    @cypher: This is from Crockford (read the end of the article), so is JSON, he designed JSON on these ideas. Personally my first exposure to this was via JSON, and working with it frequently makes for a deeper understanding of the principals. But it was confusing at first and this simple explanation is a gateway to getting to JSON.

    @iljmez & @Chris: Indexed Arrays can be handy, particularly when you quickly need the length of items. The challenging part I saw in these examples was the nested nature of the data. It is possible to use references within an indexed array that can be utilized programmatically. Consider that chris.hair and ["chris.hair"] are the same thing but myArry1 = [chris.friends.fred,chris.friends.steeve] and myArry2 = ["chris.friends.fred","chris.friends.steeve"] are not (an array of objects vs and array of strings). What is interesting though is that chris.friends.fred and [myArry20] are equal! Expanding on this idea, here is an alternate approach:

    
    var people = {
    	chris:{
    		hair:"red",
    		age:32,
    		city:"London",
    		friends:[
    			"fred",
    			"steeve"
    		]
    	},
    	fred:{
    		hair:"black",
    		age:35,
    		city:"London",
    // In addition to a string or a number
    // the value could also be a function
    		birthYear:function(){
    			var now = new Date();
    			return now.getFullYear() - this.age;
    		}
    	},
    	steeve:{
    		hair:"brown",
    		age:31,
    		city:"London"
    	}
    };
    // a clear indication that people is not an
    // indexed array is the lack of a .length
    var peopleCount = 0;
    for(var i in people){peopleCount++;}
    // this is not always a reliable approach
    // to get length, but works in this case
    var str = "There are " + peopleCount + " people in the data set.\n\n";
    for(var person in people){
    	var cprsn = people[person];
    	str+= person + " is from " + cprsn.city + ".\n";
    	str+= person + " has " + cprsn.hair + " hair.\n";
    	str+= person + " is " + cprsn.age + " years old.\n";
    	if(typeof(cprsn.friends)!=="undefined"){
    		str+= person + " has " + cprsn.friends.length + " friend(s)\n";
    		str+= "They are: " + cprsn.friends + ".\n";
    		for(var f=0;fpeople[friendName].age)?"younger":"older";
    			str+=" than " + person + "\n";
    		}
    	}
    	if(typeof(cprsn.birthYear)!=="undefined"){
    		str+= person + " was born in " + cprsn.birthYear() + ".\n";
    	}
    	str+= "\n";
    }
    alert(str);
    
  20. Wade Says:

    @Chris: the code in that last comment got fairly muddled by character stripping/replacing. Apologies to all if it does make any sense anymore….

  21. Marc Says:

    You write:
    > 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:
    and then have an example only using quoted strings not containing spaces… ;-)

  22. DaveG Says:

    @Chris: Or, shortened to obscurity:

    function loopproperties(o){
    for(i in o)
    i + ‘:’ + (typeof o[i]!== ‘object’) ? o[i] : loopproperties(o[i]) + ‘\n’;
    };
    console.log(loopproperties(o));

  23. kenman Says:

    aka “syntactic sugar”

  24. Banned in Boston Says:

    @Milo: you said

    “… If the left-hand operand resolves to âtrueâ then it is returned, otherwise the right-hand operand is returned. This is exactly the same as the âorâ operator in any other language.”

    Sorry, but not all languages work that way. For example, some languages will evaluate BOTH sides of an OR operator before checking to see if at least one of them has evaluated to true. (If memory serves, VB works that way.)

    For many programming tasks, it doesn’t matter whether the OR operator evaluates both operands first, or just the left one first. However, there are some situations where is does matter, and there are (increasingly common) JS idioms that depend on this ’short-circuit’ behavior.

    I’m also skeptical of the idea that OR operators in all languages return one of their operands (when neither of them evaluate to false). I believe that some languages return a Boolean value in that case.

    My apologies if the above comes across as pedantic, but I believe that this (seemingly subtle) bit of behavior actually is something experience Programmers care about. Personally, I know that whenever I am learning a new language I always check to see if the OR operator supports ’short-circuit’ evaluation (or not).

  25. JeanHuguesRobert Says:

    && operator “Progressive And” is nice too.

    I use it for my de&&bug( “http://virteal.com/DebugDarling”);

  26. Julien Wajsberg Says:

    - “The semicolons get replaced by commas (except for the last one which you need to omit)”
    And I’ll add that if you forget to remove the last one, the whole script is just silently ignored by Internet Explorer.

    - About the “assoative arrays really are objects”: the best of it is that it’s exactly the same with ActionScript. :-)

    - About the ternary expression: my view is that it’s just less maintenable code in the long run…

  27. Rob Says:

    As a PHP programmer who reluctantly “does a bit of Javascript”, your post and many of the following comments helped clarify things – thanks!

  28. Brett Zamir Says:

    Hello,

    Thanks for the helpful tips…

    One mistake though… Under the Associative Arrays section, you say “Want proof? – Do an alert(typeof links) or try alert(links1).”

    The first test doesn’t prove that the item is an object because arrays will also indicate “object” when tested with typeof. You could say, ‘Do an alert(links instanceof Array)’, but it will actually be true here. The item is still an array, but in JavaScript, as you can treat about anything as an object, adding properties to it will still work. Your second test indeed shows that there is no 2nd numerically-indexed item in the array, but a “real” associative array (depending on the language of comparison) with only string indexes probably wouldn’t show a numerically-indexed item either.

    So, I think the only test that you might want to list here is alert(links.length) which would give 0 and would prove that the items didn’t get added into the item property, even though they can be iterated when treating the array as an object (for…in loop), etc..

  29. Brett Zamir Says:

    Sorry, in the last sentence, I meant to say “would prove that the items didnât update the length property as they would in an array proper”

  30. Sridhar Says:

    Thats a good compilation.
    These definitely put the beginners & intermediate developers on the fast track.

    You should have also added the Prototypical $(obj). For the ones who don’t know, instead of repeatedly writing the “document.getElementById(obj)”, you can replace it with $(obj) by including a function like function $(obj) {return document.getElementById(obj);}. Henceforth, you can just say alert($(”name”).value).

    Caution about the ternary notation: Its quick to use like “var direction = (x < max) ? ‘left’ : ‘right’;”. But if you start using like

    var direction = (x < max) ? ((party bar) ? ‘left’ : ‘home’) : ((pals pool) ? ‘right’ : ‘home’);

    it definitely starts becoming unmaintainable.

    Keep up the good work.

  31. del_javascript (Javascript News) Says:

    Twitter Comment


    Wait till I come! » Blog Archive » JavaScript shortcut notations that shouldnât be black magic to the âaverage d.. [link to post]

    Posted using Chat Catcher

Leave a Reply

Wait till I come! is the blog of Christian Heilmann , a developer evangelist living and working in London, England. Download vcard.

Feed me, Seymour: Entries (RSS) and Comments (RSS).