[javascript] javascript: optional first argument in function

I have a typical javascript function with some parameters

my_function = function(content, options) { action }

if I call the function as such :

my_function (options)

the argument "options" is passed as "content"

how do i go around this so I can either have both arguments passed or just one ? thank you

This question is related to javascript

The answer is


With ES6:

function test(a, b = 3) {
   console.log(a, ' ', b);
}

test(1);      // Output: 1 3
test(1, 2);   // Output: 1 2

There is a nice read on Default parameters in ES6 on the MDN website here.
In ES6 you can now do the following:

secondDefaultValue = 'indirectSecondDefaultValue';

function MyObject( param1 = 'firstDefaultValue', param2 = secondDefaultValue ){
    this.first = param1;
    this.second = param2;
}

You can use this also as follows:

var object = new MyObject( undefined, options );

Which will set default value 'firstDefaultValue' for first param1 and your options for second param2.

Here a demonstration in a fiddle


I've created a simple library for handling optional arguments with JavaScript functions, see https://github.com/ovatto/argShim. The library is developed with Node.js in mind but should be easily ported to work with e.g. browsers.

Example:

var argShim = require('argShim');
var defaultOptions = {
  myOption: 123
};

var my_function = argShim([
    {optional:'String'},
    {optional:'Object',default:defaultOptions}
  ], function(content, options) {
    console.log("content:", content, "options:", options);
  });

my_function();
my_function('str');
my_function({myOption:42});
my_function('str', {myOption:42});

Output:

content: undefined options: { myOption: 123 }
content: str options: { myOption: 123 }
content: undefined options: { myOption: 42 }
content: str options: { myOption: 42 }

The main target for the library are module interfaces where you need to be able to handle different invocations of exported module functions.


Just to kick a long-dead horse, because I've had to implement an optional argument in the middle of two or more required arguments. Use the arguments array and use the last one as the required non-optional argument.

my_function() {
  var options = arguments[argument.length - 1];
  var content = arguments.length > 1 ? arguments[0] : null;
}

You will get the un passed argument value as undefined. But in your case you have to pass at least null value in the first argument.

Or you have to change the method definition like

my_function = function(options, content) { action }

Call like this

my_function ("", options);

Or you also can differentiate by what type of content you got. Options used to be an object the content is used to be a string, so you could say:

if ( typeof content === "object" ) {
  options = content;
  content = null;
}

Or if you are confused with renaming, you can use the arguments array which can be more straightforward:

if ( arguments.length === 1 ) {
  options = arguments[0];
  content = null;
}

my_function = function(hash) { /* use hash.options and hash.content */ };

and then call:

my_function ({ options: options });
my_function ({ options: options, content: content });

There are 2 ways to do this.

1)

function something(options) {
    var timeToLive = options.timeToLive || 200; // default to 200 if not set
    ...
}

2)

function something(timeToDie /*, timeToLive*/) {
    var timeToLive = arguments[1] || 200; // default to 200 if not set
    ..
}

In 1), options is a JS object with what ever attributes are required. This is easier to maintain and extend.

In 2), the function signature is clear to read and understand that a second argument can be provided. I've seen this style used in Mozilla code and documentation.


You could also put a check in the action like: options = !options ? content : options that sets options to the first argument if no second was passed in, and then you just set content to null (or ignore it, however you want to check that)


Like this:

my_function (null, options) // for options only
my_function (content) // for content only
my_function (content, options) // for both

You can pass all your optional arguments in an object as the first argument. The second argument is your callback. Now you can accept as many arguments as you want in your first argument object, and make it optional like so:

function my_func(op, cb) {
    var options = (typeof arguments[0] !== "function")? arguments[0] : {},
        callback = (typeof arguments[0] !== "function")? arguments[1] : arguments[0];

    console.log(options);
    console.log(callback);
}

If you call it without passing the options argument, it will default to an empty object:

my_func(function () {});
=> options: {}
=> callback: function() {}

If you call it with the options argument you get all your params:

my_func({param1: 'param1', param2: 'param2'}, function () {});
=> options: {param1: "param1", param2: "param2"}
=> callback: function() {}

This could obviously be tweaked to work with more arguments than two, but it get's more confusing. If you can just use an object as your first argument then you can pass an unlimited amount of arguments using that object. If you absolutely need more optional arguments (e.g. my_func(arg1, arg2, arg3, ..., arg10, fn)), then I would suggest using a library like ArgueJS. I have not personally used it, but it looks promising.