Tuesday, September 18, 2007

Using a default params hash :: Avoiding defaulting with ||

I saw yesterday. I'm a big fan. One pattern, though, that I have begun generally avoid is using the || operator to specify default values. Consider this code:

function doStuff(params){
params = params || {};
var foo = params.foo || 'fooValue';
var bar = params.bar || 'barValue';

I love how clean this pattern is. The API is flexible and it reads very easily. Unfortunately, there is a very subtle bug - you can't pass in values that are falsy because || uses type coercion. So this:

function doStuff(foo){
foo = foo || 'foo not specified';
alert( foo );

foo( '' );

will give you 'foo not specified' when the intent was to use an empty string. You can only rely on the default operator when falsy values cannot be valid values.

I have begun to use a default hash pattern I first saw in Ruby on Rails code (and is also used extensively in script.aculo.us):

function doStuff(params){
params = params || {};
var default = { foo : 'fooDefault', bar : 'barDefault'};
params = merge( defaults, params );

alert( params.foo );

This will give you what you want.

Here here an example merge function:

function merge(ontoObj, fromObj){
for( var i in fromObj ){
ontoObj[i] = fromObj[i];
return ontoObj;