Make Parameter optional

I've always handled optional parameters in Javascript like this:

function myFunc(requiredArg, optionalArg){   optionalArg = optionalArg || 'defaultValue';    //do stuff  } 

Is there a better way to do it?

Are there any cases where using || like that is going to fail?

Replay

Your logic fails if optionalArg is passed, but evaluates as false - try this as an alternative

if (typeof optionalArg === 'undefined') { optionalArg = 'default'; }

Or an alternative idiom:

optionalArg = (typeof optionalArg === 'undefined') ? 'default' : optionalArg;

Use whichever idiom communicates the intent best to you!

I find this to be the simplest, most readable way:

if (typeof myVariable === 'undefined') { myVariable = 'default'; }
//use myVariable here

Paul Dixon's answer (in my humble opinion) is less readable than this, but it comes down to preference.

insin's answer is much more advanced, but much more useful for big functions!

EDIT 11/17/2013 9:33pm: I've created a package for Node.js that makes it easier to "overload" functions (methods) called parametric.

In ECMAScript 2015 (aka "ES6") you can declare default argument values in the function declaration:

function myFunc(requiredArg, optionalArg = 'defaultValue') {
    // do stuff
}

More about them in this article on MDN (despite the article title, they're called "arguments," not "parameters," in JavaScript).

This is currently only supported by Firefox, but as the standard has been completed, expect support to improve rapidly.

If you need to chuck a literal NULL in, then you could have some issues. Apart from that, no, I think you're probably on the right track.

The other method some people choose is taking an assoc array of variables iterating through the argument list. It looks a bit neater but I imagine it's a little (very little) bit more process/memory intensive.

function myFunction (argArray) {
    var defaults = {
        'arg1'  :   "value 1",
        'arg2'  :   "value 2",
        'arg3'  :   "value 3",
        'arg4'  :   "value 4"
    }

    for(var i in defaults)
        if(typeof argArray[i] == "undefined")
               argArray[i] = defaults[i];

    // ...
}

Ideally, you would refactor to pass an object and merge it with a default object, so the order in which arguments are passed doesn't matter (see the second section of this answer, below).

If, however, you just want something quick, reliable, easy to use and not bulky, try this:


A clean quick fix for any number of default arguments

  • It scales elegantly: minimal extra code for each new default
  • You can paste it anywhere: just change the number of required args and variables
  • If you want to pass undefined to an argument with a default value, this way, the variable is set as undefined. Most other options on this page would replace undefined with the default value.

Here's an example for providing defaults for three optional arguments (with two required arguments)

function myFunc( requiredA, requiredB,  optionalA, optionalB, optionalC ) {

  switch (arguments.length - 2) { // 2 is the number of required arguments
    case 0:  optionalA = 'Some default';
    case 1:  optionalB = 'Another default';
    case 2:  optionalC = 'Some other default';
    // no breaks between cases: each case implies the next cases are also needed
  }

}

Simple demo. This is similar to roenving's answer, but easily extendible for any number of default arguments, easier to update, and using arguments not Function.arguments.


Passing and merging objects for more flexibility

The above code, like many ways of doing default arguments, can't pass arguments out of sequence, e.g., passing optionalC but leaving optionalB to fall back to its default.

A good option for that is to pass objects and merge with a default object. This is also good for maintainability (just take care to keep your code readable, so future collaborators won't be left guessing about the possible contents of the objects you pass around).

Example using jQuery. If you don't use jQuery, you could instead use Underscore's _.defaults(object, defaults) or browse these options:

function myFunc( args ) {
  var defaults = {
    optionalA: 'Some default',
    optionalB: 'Another default',
    optionalC: 'Some other default'
  };
  args = $.extend({}, defaults, args);
}

Here's a simple example of it in action.

Similar to Oli's answer, I use an argument Object and an Object which defines the default values. With a little bit of sugar...

/**
 * Updates an object's properties with other objects' properties. All
 * additional non-falsy arguments will have their properties copied to the
 * destination object, in the order given.
 */
function extend(dest) {
  for (var i = 1, l = arguments.length; i < l; i++) {
    var src = arguments[i]
    if (!src) {
      continue
    }
    for (var property in src) {
      if (src.hasOwnProperty(property)) {
        dest[property] = src[property]
      }
    }
  }
  return dest
}

/**
 * Inherit another function's prototype without invoking the function.
 */
function inherits(child, parent) {
  var F = function() {}
  F.prototype = parent.prototype
  child.prototype = new F()
  child.prototype.constructor = child
  return child
}

...this can be made a bit nicer.

function Field(kwargs) {
  kwargs = extend({
    required: true, widget: null, label: null, initial: null,
    helpText: null, errorMessages: null
  }, kwargs)
  this.required = kwargs.required
  this.label = kwargs.label
  this.initial = kwargs.initial
  // ...and so on...
}

function CharField(kwargs) {
  kwargs = extend({
    maxLength: null, minLength: null
  }, kwargs)
  this.maxLength = kwargs.maxLength
  this.minLength = kwargs.minLength
  Field.call(this, kwargs)
}
inherits(CharField, Field)

What's nice about this method?

  • You can omit as many arguments as you like - if you only want to override the value of one argument, you can just provide that argument, instead of having to explicitly pass undefined when, say there are 5 arguments and you only want to customise the last one, as you would have to do with some of the other methods suggested.
  • When working with a constructor Function for an object which inherits from another, it's easy to accept any arguments which are required by the constructor of the Object you're inheriting from, as you don't have to name those arguments in your constructor signature, or even provide your own defaults (let the parent Object's constructor do that for you, as seen above when CharField calls Field's constructor).
  • Child objects in inheritance hierarchies can customise arguments for their parent constructor as they see fit, enforcing their own default values or ensuring that a certain value will always be used.

You can use some different schemes for that, I've always tested for arguments.length:

function myFunc(requiredArg, optionalArg){
  optionalArg = myFunc.arguments.length<2 ? 'defaultValue' : optionalArg;

  ...

-- doing so, it can't possibly fail, but I don't know if your way has any chance of failing, just now I can't think up a scenario, where it actually would fail ...

Edit: And then Paul provided one failing scenario !-)

If you're using defaults extensively, this seems much more readable:

function usageExemple(a,b,c,d){
    //defaults
    a=defaultValue(a,1);
    b=defaultValue(b,2);
    c=defaultValue(c,4);
    d=defaultValue(d,8);

    var x = a+b+c+d;
    return x;
}

Just declare this function on the global escope.

function defaultValue(variable,defaultValue){
    return(typeof variable!=='undefined')?(variable):(defaultValue);
}

Usage pattern fruit = defaultValue(fruit,'Apple');

*PS you can rename the defaultValue function to a short name, just don't use default it's a reserved word in javascript.

Loose type checking

Easy to write, but 0, '', false, null and undefined will be converted to default value, which might not be expected outcome.

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
}

Strict type checking

Longer, but covers majority of cases. Only case where it incorrectly assigns default value is when we pass undefined as parameter.

function myFunc(requiredArg, optionalArg) {
    optionalArg = typeof optionalArg !== 'undefined' ? optionalArg : 'defaultValue';
}

Checking arguments variable

Catches all cases but is the most clumsy to write.

function myFunc(requiredArg, optionalArg1, optionalArg2) {
    optionalArg1 = arguments.length > 1 ? optionalArg1 : 'defaultValue';
    optionalArg2 = arguments.length > 2 ? optionalArg2 : 'defaultValue';
}

ES6

Unfortunately this has very poor browser support at the moment

function myFunc(requiredArg, optionalArg = 'defaultValue') {

}

If you're using the Underscore library (you should, it's an awesome library):

_.defaults(optionalArg, 'defaultValue');

Don't know why @Paul's reply is downvoted but the validaition against null is a good choice. May be more affirmative example will make sense better:

In JS a missed parameter is like a declared variable that is not initialized (just var a1;). And the equality operator converts the undefined to null so this works great with both value types and objects and this is how CoffeeScript handles optional parameters.

function overLoad(p1){
    alert(p1 == null); // caution, don't use the strict comparison: === won't work.
    alert(typeof p1 === 'undefined');
}

overLoad(); // true, true
overLoad(undefined); // true, true. Yes, undefined is treated as null for equality operator.
overLoad(10); // false, false

function overLoad(p1){
    if (p1 == null) p1 = 'default value goes here...';
    //...
}

Though, there are concerns that for the best semantics is typeof variable === 'undefined' is slightly better. I'm not about to defense this since it's the matter of underlying API how a function is implemented, it should not interest the API user.

Should also add that here's the only way to physically make sure any argument were missed, using the in operator which unfortunately won't work with the parameter names so have to pass an index of the arguments.

function foo(a, b) {
    // Both a and b will evaluate to undefined when used in an expression
    alert(a); // undefined
    alert(b); // undefined

    alert("0" in arguments); // true
    alert("1" in arguments); // false
}

foo (undefined);

The test for undefined is unnecessary and isn't as robust as it could be because as user568458 pointed out the solution provided fails if null or false is passed. Users of your API might thing false or null would force the method to avoid that param.

function PaulDixonSolution(required, optionalArg){
   optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
   console.log(optionalArg);
};
PaulDixonSolution("required");
PaulDixonSolution("required", "provided");
PaulDixonSolution("required", null);
PaulDixonSolution("required", false);

The result is:

defaultValue
provided
null
false

Those last two are potentially bad. Instead try:

function bulletproof(required, optionalArg){
   optionalArg = optionalArg ? optionalArg : "defaultValue";;
   console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);

Which results in:

defaultValue
provided
defaultValue
defaultValue

The only scenario where this isn't optimal is when you actually have optional params that are meant to be booleans or intentional null.

I am used to seeing a few basic variations on handling optional variables. Sometimes, the relaxed versions are useful.

function foo(a, b, c) {
  a = a || "default";   // matches 0, "", null, undefined, NaN, false.
  a || (a = "default"); // matches 0, "", null, undefined, NaN, false.

  if (b == null) { b = "default"; } // matches null, undefined. 

  if (typeof c === "undefined") { c = "default"; } // matches undefined.
}

The falsy default used with variable a is, for example, used extensively in backbone.js.

Hm, I have read all above answers, and maybe the simplest would be to put it like this:

function foo(a)
{
  a = a || 'my_default_value';
}

Correct me if I'm wrong, but this seems like the simplest way (for one argument, anyway):

function myFunction(Required,Optional)
{
    if (arguments.length<2) Optional = "Default";
    //Your code
}

I suggest you to use ArgueJS this way:

function myFunc(){
  arguments = __({requiredArg: undefined, optionalArg: [undefined: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

You can also replace undefined by the type of the argument you expect to receive, like this:

function myFunc(){
  arguments = __({requiredArg: Number, optionalArg: [String: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

Those ones are shorter than the typeof operator version.

function foo(a, b) {
    a !== undefined || (a = 'defaultA');
    if(b === undefined) b = 'defaultB';
    ...
}

This is what I ended up with:

function WhoLikesCake(options) {
  options = options || {};
  var defaultOptions = {
    a : options.a || "Huh?",
    b : options.b || "I don't like cake."
  }
  console.log('a: ' + defaultOptions.b + ' - b: ' + defaultOptions.b);

  // Do more stuff here ...
}

Called like this:

WhoLikesCake({ b : "I do" });

Folks -

After looking at these and other solutions, I tried a number of them out using a snippet of code originally from W3Schools as a base. You can find what works in the following. Each of the items commented out work as well and are that way to allow you to experiment simply by removing individual comments. To be clear, it is the "eyecolor" parameter that is not being defined.

function person(firstname, lastname, age, eyecolor)
{
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
this.eyecolor = eyecolor;
// if(null==eyecolor)
//   this.eyecolor = "unknown1";
//if(typeof(eyecolor)==='undefined')
//   this.eyecolor = "unknown2";
// if(!eyecolor)
//   this.eyecolor = "unknown3";
this.eyecolor = this.eyecolor || "unknown4";
}

var myFather = new person("John", "Doe", 60);
var myMother = new person("Sally", "Rally", 48, "green");

var elem = document.getElementById("demo");
elem.innerHTML = "My father " +
              myFather.firstname + " " +
              myFather.lastname + " is " +
              myFather.age + " with " +
              myFather.eyecolor + " eyes.<br/>" +
              "My mother " +
              myMother.firstname + " " +
              myMother.lastname + " is " +
              myMother.age + " with " +
              myMother.eyecolor + " eyes.";

function Default(variable, new_value)
{
    if(new_value === undefined) { return (variable === undefined) ? null : variable; }
    return (variable === undefined) ? new_value : variable;
}

var a = 2, b = "hello", c = true, d;

var test = Default(a, 0),
test2 = Default(b, "Hi"),
test3 = Default(c, false),
test4 = Default(d, "Hello world");

window.alert(test + "\n" + test2 + "\n" + test3 + "\n" + test4);

http://jsfiddle.net/mq60hqrf/

This works for me:

function dest(site)
{
  if(!site)
   site="angelcool.net";//default value

}

Landed to this question, searching for default parameters in EcmaScript 2015, thus just mentioning...

With ES6 we can do default parameters:

function doSomething(optionalParam = "defaultValue"){
    console.log(optionalParam);//not required to check for falsy values
}

doSomething(); //"defaultValue"
doSomething("myvalue"); //"myvalue"

With ES2015 you can take advantage of Object.assign which can replace $.extend() or _.defaults()

function myFunc(requiredArg, options = {}) {
  const defaults = {
    message: 'Hello',
    color: 'red',
    importance: 1
  };

  const settings = Object.assign({}, defaults, options);

  // do stuff
}

I tried some options mentioned in here and performance tested them. At this moment the logicalor seems to be the fastest. Although this is subject of change over time(different javascript engine versions)

This are my results (Microsoft Edge 20.10240.16384.0)

Function executed            Operations/sec     Statistics
TypeofFunction('test');          92,169,505     ±1.55%   9% slower
SwitchFuntion('test');            2,904,685     ±2.91%  97% slower
ObjectFunction({param1: 'test'});   924,753     ±1.71%  99% slower
LogicalOrFunction('test');      101,205,173     ±0.92%     fastest
TypeofFunction2('test');         35,636,836     ±0.59%  65% slower

This performance test can be easily replicated on: http://jsperf.com/optional-parameters-typeof-vs-switch/2

This is the code of the test:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
Benchmark.prototype.setup = function() {
    function TypeofFunction(param1, optParam1, optParam2, optParam3) {
        optParam1 = (typeof optParam1 === "undefined") ? "Some default" : optParam1;
        optParam2 = (typeof optParam2 === "undefined") ? "Another default" : optParam2;
        optParam3 = (typeof optParam3 === "undefined") ? "Some other default" : optParam3;
    }

    function TypeofFunction2(param1, optParam1, optParam2, optParam3) {
        optParam1 = defaultValue(optParam1, "Some default");
        optParam2 = defaultValue(optParam2, "Another default");
        optParam3 = defaultValue(optParam3, "Some other default");
    }

    function defaultValue(variable, defaultValue) {
        return (typeof variable !== 'undefined') ? (variable) : (defaultValue);
    }

    function SwitchFuntion(param1, optParam1, optParam2, optParam3) {
        switch (arguments.length - 1) { // <-- 1 is number of required arguments
            case 0:
                optParam1 = 'Some default';
            case 1:
                optParam2 = 'Another default';
            case 2:
                optParam3 = 'Some other default';
        }
    }

    function ObjectFunction(args) {
        var defaults = {
            optParam1: 'Some default',
            optParam2: 'Another default',
            optParam3: 'Some other default'
        }
        args = $.extend({}, defaults, args);
    }

    function LogicalOrFunction(param1, optParam1, optParam2, optParam3) {
        optParam1 || (optParam1 = 'Some default');
        optParam2 || (optParam1 = 'Another default');
        optParam3 || (optParam1 = 'Some other default');
    }
};
</script>

Some code intel tools, in particular the WebStorm IDE and perhaps jshint, give warnings when you call a function with less arguments than declared:

function foo(a, b) {
    if (typeof b === 'undefined') {
        b = 5;
    }
    …
}

foo(1); /* warning */

What you can do instead is this:

function foo(a /*, b */) {
    var b = arguments.length > 1 ? arguments[1] : 2;
    …
}

foo(1);

Note that the b argument is declared in a comment for clarity.

function foo(requiredArg){
  if(arguments.length>1) var optionalArg = arguments[1];
}

Category: javascript Time: 2008-09-29 Views: 1

Related post

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development

search

Front-end development

Database

development tools

Open Platform

Javascript development

.NET development

cloud computing

server

Copyright (C) avrocks.com, All Rights Reserved.

processed in 0.207 (s). 12 q(s)