parentNode.org

The building blocks of a solid frontend.

Default Arguments in JavaScript Functions

Posted in JavaScript by fatbrain on the June 16th, 2006

I often run into people who need (for reasons that are beyond me) to be able to give arguments in a javascript function default values. Kinda like what you have in C/C++:

void foo(int a, int b = 42) { ... }

I felt an urge to do it, so I sat down for a few minutes, trying to conjure something nifty that would be intuitive enough for even me to use.

The solution I came up with, and that hopefully will put an end to the I-need-default-arguments-in-javascript rant for good.

The solution is quite simple, and very intuitive. It may have some shortcomings but keep in mind I didn’t explicitly write it for you. You could probably modify my solution to fit your needs anyway.

I’ve seen alot of developers (including myself, long time ago) using this pattern as a workaround for the lack of built-in support for default-arguments.

function foo(a, b)
{
  a = typeof(a) != 'undefined' ? a : 42;
  b = typeof(b) != 'undefined' ? b : 'default_b';
  ...
}

Which most developers probably find sufficient, I don’t.

The solution may look scary at a quick first glance, but bear with me. I’ll start by writing the framework-code. The code that will be required for this thing to work.

Function.prototype.defaults = function()
{
  var _f = this;
  var _a = Array(_f.length-arguments.length).concat(
    Array.prototype.slice.apply(arguments));
  return function()
  {
    return _f.apply(_f, Array.prototype.slice.apply(arguments).concat(
      _a.slice(arguments.length, _a.length)));
  }
}

See that wasn’t so scary :).

In order for this to work you have to declare you functions in a special way. There are basicly two ways of declaring a function.

function foo(a, b)
{
  ...
}

Is identical to (apart from the lexical difference, and some other minor things)

var foo = function(a, b)
{
  ...
}

In order for this solution to work you have to declare all functions on which you wish to have default-arguments the latter way.

Usage

var foo = function(a, b)
{
  ...
}.defaults(42, 'default_b');

Is identical to the first code-block but without adding any code in the function-body.

Example

var bar = function(a, b)
{
}.defaults('default_b');

bar();
// a = undefined, b = 'default_b'

bar(1);
// a = 1, b = 'default_b'

bar(1, 'some_value');
// a = 1, b = 'some_value'