
Default Parameters in JavaScript - joshuacc
http://designpepper.com/blog/drips/default-parameters-in-javascript
======
STRML
For people who like a bit more clarity, underscore also has a _.defaults
syntax:

    
    
      function foo(opts){
        var defaults = {bar: "baz", foo: "biff"};
        _.defaults(opts, defaults);
        // do things with opts here...
      }
    

The difference between _.defaults and _.extend is significant; _.extend will
overwrite all properties in the first object with those defined in the second
(and third, fourth, etc.), while _.defaults will only overwrite properties
that are null or undefined.

The advantage is, using _.defaults, that you aren't passing a defaults object
around within the body of your method and using it as if it were the opts, or
reassigning to yet another var (see `finalParams` defined in the last
example). This makes the method a bit clearer.

~~~
zimbatm
One problem though it that it's modifying the opts parameter so it might
create unwanted side-effects.

    
    
        var myopts = {foo: 1}
        foo(myopts)
        console.log(myopts) // => {foo: 1, bar: "baz"}

~~~
masklinn
As with _.extend, _.defaults takes 1..n arguments and will fold 2..n into 1.
If you fear callers will pass in an object they rely on for function options
(doubtful, but why not) you can just write:

    
    
        var actual_opts = _.defaults({}, opts, {
            // Your defaults here
        });
    

where ``opts`` is the options object passed in.

This also fixes the issue of a caller passing in no options (or "null" or
"undefined") without having to add an `||`

------
leeoniya
for many cases the following will work well enough:

    
    
        function(arg1, arg2) {
          arg1 = arg1 || "foo";
          arg2 = arg2 || "bar";
        }
    

it will fail of course if you expect to accept falsy args tho, then you need a
bit moar kludge...

    
    
        arg1 = arg1 !== 0     ? 1234  : arg1;
        arg1 = arg1 !== false ? "foo" : arg1;
        arg1 = arg1 !== null  ? "foo" : arg1;
        arg1 = arg1 !== ""    ? "foo" : arg1;
    

and if you expect to accept multiple types of falsy values for any one
argument (which requires a lot more kludge), you should probably change your
API :)

~~~
STRML
You are correct, except this will not work in the significant case where any
falsy value is passed ("", 0, null, NaN... I exclude undefined because that is
the intended behavior) or with booleans.

A slightly more verbose, yet hardy syntax would go like this:

    
    
      function foo(arg1, arg2){
        arg1 = arg1 === undefined ? "foo" : arg1;
        arg2 = arg2 === undefined ? "bar" : arg2;
      }
    

This would catch the intended behavior, which is to fill a parameter when it
is not supplied at all.

~~~
leeoniya
already was updating :)

------
noonat
If you want to allow undefined to be passed as a valid non-default value for a
trailing parameter, you can also use arguments.length to determine how many
arguments were explicitly specified.

    
    
        var foo = function(a, b) {
            if (arguments.length < 2) {
                b = 'some default value';
            }
            // ...
        };

~~~
ajanuary
I wish jQuery's setter methods worked this way. It's too easy to accidentally
turn a setter into a getter.

------
jlongster
It should be noted that ES6 implements default parameters, so they are coming
to javascript soon:
[http://wiki.ecmascript.org/doku.php?id=harmony:parameter_def...](http://wiki.ecmascript.org/doku.php?id=harmony:parameter_default_values)

~~~
weego
but not reliably to a browser for some quite considerable time.

------
insin
TL;DR version:

    
    
        function(kwargs) {
          kwargs = _.extend({param1: true, param2: 42}, kwargs)
          // ...
        }

~~~
masklinn

        var args = _.defaults({}, kwargs, {param1: true, param2: 42}).

------
bm1362
I thought this was common knowledge? If you've read any JS library code you'd
have seen this before. I'm not sure what the 'best' library to study is these
days- I remember there was HN discussion about it and someone mentioned
underscore.js since it was simple utilities.

~~~
joshuacc
It is certainly common knowledge in some groups, but not in others. There are
plenty of people who are primarily designers who know just a little JS, as
well as developers in other languages who have learned just enough JS to get
by.

------
jonjaques
Library agnostic version if anyone cares for it:
<https://gist.github.com/jonjaques/3036701>

------
goldfeld
Or you could just use CoffeeScript.

