Missing and Default Parameters in JavaScript

Passing parameters to JavaScript functions seems simple enough. Since the language is weakly-typed, all the parameters in the call are simply comma-separated.

And in the definition of the function it can get no more complicated than that–a comma-separated list of parameters.

Not much room for flexibility, is there?

But let’s take a closer look. Suppose you don’t pass all the parameters that a function is expecting. What happens?

If you shortchange a function, all the parameters you failed to supply are undefined.

What happens if you give more parameters than the function expects? They are ignored, but you can find they are still accessible in an array-like list called arguments. (No, it’s not an array. While it does have a length, it’s missing the methods that come with arrays.)

Now What?

So we’ve revealed a bit of flexibility–JavaScript won’t come to a screaming halt if you supply more or less parameters than a function expects. It’s more flexible in handling parameters than we might have suspected.

Some languages allow you to specify default parameters. Can JavaScript do that? Well, it’s not in the spec, but JavaScript programmers commonly provide default parameters using JavaScript’s || operator.

a = a || 1;

If a is undefined, a will be assigned 1. A will also be assigned 1 if a is 0. That’s not always what you want, so sometimes a condition is best:

if (a===undefined) {
  a=1;
}

Let’s try one. We’ll make a function that takes three parameters.

  • a will have the default value of 1
  • b will have the default value of 2
  • c will have the default value of 3
function test(a,b,c) {
    a=a||1;
    b=b||2;
    c=c||3;
    console.log(a,b,c);
}

We can call it like this:

test(1,2,5);
test(undefined,3,undefined);
test();

And get output like this:

1,2,5
1,3,3
1,2,3

If you have a lot of parameters coming in, that can get messy fast. Is there a better way?

There Is a Better Way

More than a few programmers have taken a stab at providing a nice default parameter implementation, and JavaScript is flexible enough to provide many ways to do it.

Most of these solutions feel over-engineered to me, so I spent some time thinking about the problem and came up with my own solution. I wrote a function called defaultHandler. This is going to be easy! Take a look:

    defaultHandler=function(defaults,params) {
        var i;
        for (i in params) {
            defaults[i]=params[i];
        }
        return defaults;
    }

We start with the “defaults” object that was passed in. Obviously, this holds all the default values for the parameters we expect to get passed in. Then we spin through everything that was passed in as a parameter and add it to the defaults, overwriting values when we run into identical keys.

Simple. Too simple, perhaps. The trick must be in how we use it. Is that it? Well, here’s an example.

    function test(obj) {
        var params=defaultHandler({a:1,b:2,c:3},obj);
        console.log(params);
    }

Hmm. Not much going on there, either. I told you this was going to be easy!

Here, I call our test function:

    test({a:5,x:"tuna"});
    test({});
    test({b:10,y:5});

And get the following output:

Object a=5 b=2 c=3 x=tuna
Object a=1 b=2 c=3
Object a=1 b=10 c=3 y=5

That’s all there is to it. Instead of passing parameters, we always pass in one single object that holds all the parameters.

In effect, we’re ignoring JavaScript’s “almost an array, but not really” parameter-passing system, and using a full-blown object to do the parameter passing work. Since objects can hold anything (numbers, booleans, arrays, objects, functions, probably even regex descriptions), nothing has changed except the packaging and naming of parameters. And we’ve gained tons of flexibility.

Come to think of it, you don’t even really need the default handler. That’s just a nice way of pruning down the parameters which need to be passed.

Why Would I Do This?

Imagine you’ve written an operating system. It has a nice windowing user interface. You have function calls like “OpenWindow” that take some parameters. In a later version of the interface you want to start adding parameters to the function.

It can get messy. You want to keep backwards compatibility so old applications don’t break. So maybe you have a slew of new functions like “NewOpenWindow.” Then you come out with another revision and you want to add still more parameters.

When it gets silly enough, you look for another solution. The Amiga guys solved this problem with taglists. Taglists were much like an object–a list of names and corresponding values. You only supply the parameters you want to.

That was the first time I saw this sort of solution. They added an OpenWindowTags() function and that solved the problem forever. Unfortunately, in the case of the Amiga, “forever” didn’t last very long.

It’s a great solution for APIs of JavaScript libraries. You can add new stuff in the future without breaking any old calls to your library.

A good rule of thumb is to use JavaScript’s normal parameter conventions whenever the number of parameters are small and it’s inconceivable that they might change. Otherwise, pass in an object.

In Which I Discover I’m More Interesting and Provocative in Spanish

Some terrific Spanish-speaking people linked to this blog. Thanks to all those English-as-a-second-language readers out there who take the time to work through a blog like mine.

Google’s delightful Spanish-to-English translation…

Dreaming in Javascript

The more I write JavaScript, but I’m sure thinking that the language domain. Just when I decide one way to do something, I can think of another way of doing amazingly better.

JavaScript is a language that seems to have grown up with the sun shining on him. While Java is the caretaker of the beach, blonde boat and surrounded by plastic boobs embobados, JavaScript is disturbingly mysterious maiden forest that you can barely glimpse for a moment while you open passage between blackberries and brambles.

Two assertions of the most intriguing blog Dreaming in Javascript. Undoubtedly he invented the word recommended.

They are quoting from The Object Slinger post. Who knew I had such a flair for writing in Spanish?