-1

I want to write a function that takes an optional argument and changes its behavior depending on whether or not that argument is provided. This is the first way I thought to do this:

function foo(optionalArg) {
    if (optionalArg) {
        // do something with the optionalArg
    } else {
        // do something different
    }
}

Is this the best way to do this, or is there a safer/better way?

EDIT: If you actually read the question, you'll notice that it's different than the "duplicates" some claim this is. I know how to provide default values to a function's arguments; I found those links when I was trying to figure this out on my own first. But I'm not looking for how to do that. I'm looking for the best way to change my function's behavior based on whether or not the argument was provided.

bobbyz
  • 4,946
  • 3
  • 31
  • 42
  • @Juhana that doesn't change behavior, it provides defaults for optional arguments. – ssube Jun 16 '16 at 16:48
  • @Juhana This isn't a duplicate. Those other posts don't answer my question. There is a difference. – bobbyz Jun 17 '16 at 16:59
  • @nicael This isn't a duplicate. Those other posts don't answer my question. There is a difference. – bobbyz Jun 17 '16 at 16:59
  • @torazaburo This isn't a duplicate. Those other posts don't answer my question. There is a difference. – bobbyz Jun 17 '16 at 17:00

2 Answers2

1

Specificity is often better and arguments that were declared but not provided are undefined, so you could do:

function foo(optionalArg) {
    if (optionalArg !== undefined) {
        // do something with the optionalArg
    } else {
        // do something different
    }
}

Using if (optionalArg) will treat falsy values (0, '', etc) as if they were omitted entirely, which is probably not what you want.

This method will still return a false negative if the argument was explicitly set to undefined (as t.niese mentioned in the comments), which is rare but possible. You could check arguments.length to work around that, but arguments is not available in ES6 arrow functions. For ES5, using:

if (arguments.length > 0) { ...

ought to do the trick, otherwise you can use:

function foo(...args) {
  if (args.length > 0) { ...

and collect your own array, which will work in arrow functions:

(...args) => {
  if (args.length > 0) { ...
ssube
  • 47,010
  • 7
  • 103
  • 140
  • This would obfuscate that case when value passed as argument is `undefined`. Testing against `arguments.length` is a better way to determin how many arguments are passed. – t.niese Jun 16 '16 at 16:57
  • Checking `arguments` is not always available, especially not in ES6 arrow functions. I am adding an example using an equivalent array that will work across the board. – ssube Jun 16 '16 at 17:01
  • Awesome, great examples. Thanks so much. This wasn't answered by the other posts some people claim this is a duplicate of. – bobbyz Jun 17 '16 at 17:06
1

The way you are doing is it fine, but here's a few tips.

1) In ES6 you could have a default argument in case one is not supplied:

function foo(optionalArg = 'something cool') {
   // have your function go about its business as usual
}

2) Same as above, except not using ES6:

function foo(optionalArg) {
   if (optionalArg === undefined) {
      optionalArg = 'something cool'
   }
   // have your function go about its business as usual
}

3) Check your argument against undefined to avoid false positives:

function foo(optionalArg) {
    if (optionalArg !== undefined) {
        // do something with the optionalArg
    } else {
        // do something different
    }
}

4) Place the longer block in the else statement for optimal readability:

function foo(optionalArg) {
   if (optionalArg !== undefined) {
     // do something with the optionalArg
   } else {
     // do something different
     // big
     // huge
     // grandiose
     // epic
   }
}

I hope that helps!

m-a-r-c-e-l-i-n-o
  • 2,622
  • 18
  • 26
  • Awesome, helps a ton, thanks so much. This wasn't answered by the other posts some people claim this is a duplicate of. – bobbyz Jun 17 '16 at 17:28