What are JavaScript options objects?

In JavaScript, options objects are a common pattern for passing arguments into a function. This article explains how they work and why using them makes your code more readable.

What is an options object?

An options object is a normal JavaScript object that contains a set of named parameters that are passed into a function.

For example, the jQuery.ajax function uses an options object. This function can take up to 34 parameters, all of which are optional.

$.ajax({
    url: "http://date.jsontest.com/",
    success: function (data) {console.log(data);},
    cache: true,
    timeout: 500
});

Without an options object it would be much harder to understand what each parameter is for:

$.ajax(
    "http://date.jsontest.com/",
    function (data) {console.log(data);},
    true,
    500
);

Many other programming languages have a feature called "named arguments" to achieve the same objective as options objects.

When should I use options objects for my own functions?

You should consider using an options object when a function has two or more arguments. For a function with four or more arguments it's usually a good idea.

If a function only has one argument now, but you expect it to add more later, just start using an options objects now rather than having to rewrite code later.

Ultimately what decides whether an options object is better than an argument list is whether it's clear what the arguments are for. sum(4, 2) is self-evident, showDialog(true, false) isn't.

Options objects are an underused JavaScript pattern, and you can't do much harm by using them more often.

Writing your own function that accepts an options object

Here's a traditionally written function that's called by passing the arguments individually.

function showDialog (showAlertIcon, showBackdrop) {
    if (showAlertIcon) {
        alertIcon.show();
    }
    if (showDarkBackdrop) {
        backdrop.show();
    }
    dialog.show();
}

And here's how you call it:

showDialog(true, false);

The line above doesn't make it clear what the arguments stand for. You can solve this problem by rewriting the function to use an options object:

function showDialog (options) {
    if (options.showAlertIcon) {
        alertIcon.show();
    }
    if (options.showDarkBackdrop) {
        backdrop.show();
    }
    dialog.show();
}

Now showDialog can be called by passing in an object with one key/value pair for each parameter:

showDialog({
    showAlertIcon: true,
    showDarkBackdrop: false
});

This way it's clear what the two parameters do, and there's no need to look at the function definition to understand the function call.

Setting default values

Options objects also make it easy to make parameters optional. When an optional parameter isn't passed in, a default value should be used instead.

Underscore's has a _.defaults method, but it modifies the options parameter that's passed in. That can create unwanted side effects, so you should avoid using _.defaults directly.

Instead, you can write a custom function like this:

function setDefaults(options, defaults){
    return _.defaults({}, _.clone(options), defaults);
}

setDefaults creates a copy of the options argument that's passed in, which makes sure that the original options object isn't modified.

Now you can use setDefaults to configure apply parameters.

function showDialog (options) {
    var defaults = {
        showAlertIcon: false,
        showDarkBackdrop: true
    };
    options = setDefaults(options, defaults);
    if (options.showAlertIcon) {
        alertIcon.show();
    }
    if (options.showDarkBackdrop) {
        backdrop.show();
    }
    dialog.show();
}

After this change you can call showDialog with only the parameters you want to override:

showDialog({showDarkBackdrop: false});