JavaScript Shortcuts

JavaScript has many useful features that can decrease the amount of code you have to write. This post goes over some of my favorite shortcuts.

Using Commas To Avoid Curly Braces

The most common use of commas I've seen in JavaScript has been separating arguments and declaring multiple variables. It turns out you can actually use them in other places as well.

One useful way to use this approach is when you need to change multiple variables when a certain condition is met. By using commas you can avoid using a pair of curly braces to wrap the assignments.

In the example below we have a flattened array of values for a grid. The variables x and y are used to keep track of the current coordinates as we loop though the array.

//some information to display
var perRow = 3;
var grid = [0,0,1,0,1,0,1,0,0];

//monitor the coordinates to draw at
var x = 0, y = 0;
for(var point in grid) {
  draw(grid[point], x, y);

  //manage the position variables without
  //needing a set of curly braces
  // if reaching row limit?
  //   - reset X to zero
  //   - move down the next row
  if (++x == perRow) x = 0, y++;
}

You'll notice on that you can avoid the use of curly braces and instead use a comma to set both the x and y values as part of the same if statement. It certainly isn't a very big gain but it does reduce the amount of code by a few characters.

Use Logical Operators To Provide Defaults

One of the strengths of JavaScript is that you can pass as many (or as few) arguments as you like into any method. Unforunately, this can also make it difficult to be certain that every argument has been provided.

JavaScript has many interesting ways to evaluate true and false. Most values will evaluate as true when they are present whereas null evaluates as false. We can use this to help determine which values need a default value assigned.

Some values will evaluate as false even when they are set. This is important to keep in mind when using this approach and will be explained shortly.

//create a message for showing 
var showError = function(error, title, type) {

  //if the parameter is not known then the
  //next value will be used
  dialog.show(
    error || window.error || "An unexpected error occurred.",
    title || "Error",
    type || dialog.styles.error
    );
}

In this sample, if an argument isn't provided JavaScript will skip it and attempt to use the next value. Eventually, if nothing usable is found the code will simply use the last value which will be the default value. This avoids using a bunch of if/then statements to find a value to use.

This approach works well when you're checking for missing (null) values, however, this doesn't work well when the value provided evaluates as false even when set.

//examples where 'or' could get you into trouble
0 || 100 // 100
"" || "green" // 'green'
NaN || -1 // -1
false || true  // true

Each example above has a value provided but will still evaluate as false! This results in the provided value being ignored and the default value being used instead. In those instances you're probably better off using a ternary operator to find the correct default.

//using a ternary instead of 'or'
typeof value == "number" ? value : 100 // value if is a number
typeof value == "string" ? value : "green" // value if is a string
isNan(value) ? value : -1 // value if is NaN
value === false ? false : true  // false is set to 'false' 

Additional Information For Anonymous Functions

Being able to pass functions around as arguments one of the best features of JavaScript (or any language that allows passing methods for that matter).

However, this can be problematic when you need to provide more than a couple arguments to the anonymous function. The example below is a simple method that loops through a collection that provides additional loop information as part of the method call.

//action requires too many arguments!!
var each = function(collection, action) {
  for(var item in collection) {
        var value = collection[item];
    //...

    action(value, index, key, even, odd, total, first, last, remaining);
  }
};

In order to have access to the values provided we must make sure to include the parameter as part of the anonymous function which can be annoying if all you really need is one of the last values.

Fortunately, we can use the call or apply methods to change the context of the this object within the anonymous function.

//simple loop method with additional information 
//available for each record
var each = function(collection, action) {

  //get the total records to use
  var count = 0;
  if (collection instanceof Array) count = collection.length;
  else for(var item in collection) count++;

  //start looping through the collection
  var index = 0;
  for(var item in collection) {
    var value = collection[item]
    var detail = {
      index: index,
      key: item,
      even: index % 2 == 0,
      odd: index % 2 != 0,
      total: count,
      first: index == 0,
      last: index == (count - 1),
      remaining: (count - 1) - index
    };

    //use 'call' to invoke the action and use the
    //first parameter to specify what 'this' is in
    //the method
    if (action.call(detail, value) === false) break; //or return
    index++;
  }
};

//using the each function. \
//the 'this' object is the same as the 'details'
//object created on line 14
each(records, function(record) {

  //the 'record' argument is from the collection
  var row = $("<li/>").text(record.name);

  //'this' has additional information about the loop
  if (this.even) row.addClass("alt-row");
  if (this.first) row.addClass("header");

});

By changing the context of this we are able to provide much more information to the anonymous function without needing to include a slew of unnecessary arguments.

The apply command is very similar to the call command except that is uses an array to pass in arguments instead of each one separated by a comma. The apply command is useful when you do not know how many arguments are needed for the method call.

April 10, 2011

JavaScript Shortcuts

Samples and explanations of helpful shortcuts to use when writing JavaScript.