简体   繁体   中英

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

You have to decide as which parameter you want to treat a single argument. You cannot treat it as both, content and options .

I see two possibilities:

  1. Either change the order of your arguments, ie function(options, content)
  2. Check whether options is defined:

     function(content, options) { if(typeof options === "undefined") { options = content; content = null; } //action }

    But then you have to document properly, what happens if you only pass one argument to the function, as this is not immediately clear by looking at the signature.

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

and then call:

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

Like this:

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

With ES6:

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

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

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;
}

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

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.

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 eg 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.

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 (eg 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.

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 }

You could also put a check in the action like: options = !options ? content : options 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)

像这样打电话

my_function ("", options);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM