17

What is the best way to create a function that takes optional arguments in nodejs?

for example I know this method:-

    function optionalArguments(a,b){
        var a = a || "nothing";
        var b = b || "nothing";
    } 

but in this case if I do this :

optionalArguments(false,false)

both a and b return "nothing" although I have passed an argument.

and also I get unexpected token error when I call the function like this :

optionalArguments(,"xxx");

Is there a better or a standard method to tackle optional arguments in nodejs?

Any help is appreciated. Thanks in advance.

azero0
  • 2,220
  • 3
  • 20
  • 31

4 Answers4

37

If you are using Node.js v6 (or higher), you have access to default parameters.

function optionalArguments(a="nothing", b="nothing") {
  return `a: ${a}, b: ${b}`;
}

Then

optionalArguments(false, false)     // 'a: false, b: false'
optionalArguments('this')           // 'a: this, b: nothing'
optionalArguments()                 // 'a: nothing, b: nothing'
optionalArguments(undefined,'that') // 'a: nothing, b: that'
waternova
  • 1,472
  • 3
  • 16
  • 22
16

You do that exactly like for client side javascript.

The way you suggest does work but is, as you noticed, painful when the arguments that can be omitted aren't the last ones.

In that case, what's commonly used is an "options" object :

function optionalArguments(options){
    var a = options.a || "nothing";
    var b = options.b || "nothing";
}

Note that || is dangerous. If you want to be able to set arguments like false, "", 0, NaN, null, you have to do it like this :

function optionalArguments(options){
    var a = options.a !== undefined ? options.a : "nothing";
    var b = options.b !== undefined ? options.b : "nothing";
}

A utility function can be handy if you do this a lot :

function opt(options, name, default){
     return options && options[name]!==undefined ? options[name] : default;
}

function optionalArguments(options){
    var a = opt(options, 'a', "nothing");
    var b = opt(options, 'b', "nothing");
}

This way you can even call your function with

optionalArguments();
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • but when I pass options.a=false I still get "nothing" although the value should have been false is there a way to tackle this? – azero0 May 10 '14 at 06:01
  • 2
    Object deconstruction can become very useful in this case. The function definition can be rewritten as `function optionalArguments({a, b}) { /* use a and b like normal parameters*/ } optionalArguments({a: 'foo', b: 42});`. Couldn't find a lot of official information about it though: http://wiki.ecmascript.org/doku.php?id=harmony:destructuring – Felix Kling May 10 '14 at 06:04
  • @dystroy I am sure you meant `options[name]` – thefourtheye May 10 '14 at 06:10
  • Thanks for the function pageOptions, i was wondering how to use it. – Usman Iqbal Oct 25 '17 at 07:23
2

The || is just the regular old or operator. It comes in handy when the value is expected to not be falsey. But, if values like 0, false, or null are valid and expected, you need to take a different approach.

== null

To check to see if a non-null value was passed, use == null. This will return true when null or undefined are passed in:

function optionalArguments (a, b) {
    a = a == null ? "nothing" : a;
    b = b == null ? "nothing" : b;
    ...
}

In most cases, this is the best approach for implementing optional parameters. It allows the caller to pass null when the default value is desired. It's particularly useful when a caller wants to pass a value for the second argument, but use the default for the first. Eg, optionalArguments(null, 22)

=== undefined

If null is a valid and expected value, compare as above using undefined and the === operator. Make sure that you are using a valid value of undefined for your comparison. It is possible for a script to say var undefined = 0, causing endless headaches for you. You can always do === void 0 to test for undefined.

arguments.length

What if I call your function like this?

optionalArguments("something", void 0);

In this case, I did pass a value, but that value is undefined. There may be times when you truly want to detect whether an argument was passed in or not. In this case, you need to check the arguments.length:

function optionalArguments (a, b) {
    a = arguments.length > 0 ? a : "nothing";
    b = arguments.length > 1 ? b : "nothing";
    ...
}
gilly3
  • 87,962
  • 25
  • 144
  • 176
  • Did you really see a case where it was useful to detect if the caller passed `undefined` as last argument rather than passing nothing ? I'd say this was an utterly wrong design... – Denys Séguret May 10 '14 at 06:14
  • I don't remember the details, but I do remember a time once when I wanted to see if an argument was passed, even if it was `undefined`. I agree, it's not a great design. – gilly3 May 10 '14 at 06:17
0

As an easy way to use default arguments and still be able to use the false value, you can do like this

function optionalArguments(a, b){
  a = typeof a !== 'undefined' ? a : "nothing"; 
  b = typeof b !== 'undefined' ? b : "nothing";
} 

See also alternative options on this question

Whichever option you chose, optionalArguments(, "xxx") will not be valid because the missing parameter makes the syntax invalid: the code cannot be parsed. To fix it, you can use

optionalArguments(undefined, "xxx");
Community
  • 1
  • 1
Aurélien Gasser
  • 3,043
  • 1
  • 20
  • 25
  • 1
    The `var` is unnecessary here. And if you use `a != null ? ...`, then you can also use `null` instead of `undefined` to omit the argument: `optionalArguments(null, "xxx");` (less to type ;) (only of course if `null` is not a valid value)). – Felix Kling May 10 '14 at 06:08
  • @FelixKling Thanks, I removed the extra var in my anwser. About using `null` instead of `undefined`, I think `undefined` is more adapted to describe a missing value, but I guess that's subject to opinion! – Aurélien Gasser May 10 '14 at 06:10
  • I agree! As I said, it depends on the actual use case. – Felix Kling May 10 '14 at 06:23