This question already has an answer here:
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?
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
undefined
to an argument with a default value, this way, the variable is set asundefined
. Most other options on this page would replaceundefined
with the default value.Here's an example for providing defaults for three optional arguments (with two required arguments)
Simple demo. This is similar to roenving's answer, but easily extendible for any number of default arguments, easier to update, and using
arguments
notFunction.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 leavingoptionalB
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:Here's a simple example of it in action.
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).
These are my results (Microsoft Edge 20.10240.16384.0):
This performance test can be easily replicated on: http://jsperf.com/optional-parameters-typeof-vs-switch/2
This is the code of the test:
It seems that the safest way - to deal with all \ any falsy types of supplied arguments before deciding to use the default - is to check for the existence\presence of the optional argument in the invoked function.
Relying on the arguments object member creation which doesn't even get created if the argument is missing, regardless of the fact that it might be declared, we can write your function like this:
Utilizing this behavior: We can safely check for any missing values on arguments list arbitrarily and explicitly whenever we need to make sure the function gets a certain value required in its procedure.
In the following demo code we will deliberately put a typeless and valueless undefined as a default value to be able to determine whether it might fail on falsy argument values, such as 0 false etc., or if it behaves as expected.
Now, checking few falsy argument-values to see if their presence is correctly detected and therefore evaluates to true:
Which means -they didn't fail the recognition of/as expected argument values. Here we have a check with all arguments missing, which according to our algo should acquire their default values even if they're falsy.
As we can see, the arguments arg1, arg2, arg3 and the undeclared arg4, are returning their exact default values, as ordered. Because we've now made sure that it works, we can rewrite the function which will actually be able to use them as in the first example by using: either if or a ternary condition.
On functions that have more than one optional argument, - a loop through, might have saved us some bits. But since argument names don't get initialized if their values are not supplied, we cannot access them by names anymore even if we've programmatically written a default value, we can only access them by arguments[index] which useless code readability wise.
But aside from this inconvenience, which in certain coding situations might be fully acceptable, there's another unaccounted problem for multiple and arbitrary number of argument defaults. Which may and should be considered a bug, as we can no longer skip arguments, as we once might have been able to, without giving a value, in a syntax such as:
because it will throw! Which makes it impossible for us to substitute our argument with a specific falsy type of our desired default value. Which is stupid, since the arguments object is an array-like object and is expected to support this syntax and convention as is, natively or by default!
Because of this shortsighted decision we can no longer hope to write a function like this:
in which case, we would be able to write each default value of a desired type in arguments row and be able to at least access them by args.index.
For instance this function call would yield:
as defined in our default array of arguments values. However the following is still possible:
But regretfully not:
Which would otherwise be logging:
but that's in a better world! However - for the original question - the topmost function will do just fine. e.g.:
p.s.: sorry for not preserving the types of chosen defaults in my argument inputs while writing them.
I find this to be the simplest, most readable way:
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.
Correct me if I'm wrong, but this seems like the simplest way (for one argument, anyway):
Your logic fails if optionalArg is passed, but evaluates as false - try this as an alternative
Or an alternative idiom:
Use whichever idiom communicates the intent best to you!