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:
function myFunc(requiredArg, optionalArg){
optionalArg = 1 in arguments ? optionalArg : 'defaultValue';
//do stuff
}
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.
function argCheck( arg1, arg2, arg3 ){
arg1 = 0 in arguments || undefined;
arg2 = 1 in arguments || false;
arg3 = 2 in arguments || 0;
var arg4 = 3 in arguments || null;
console.log( arg1, arg2, arg3, arg4 )
}
Now, checking few falsy argument-values to see if their presence is correctly detected and therefore evaluates to true:
argCheck( "", 0, false, null );
>> true true true 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.
argCheck( );
>> undefined false 0 null
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:
argCheck("a",,22,{});
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:
function argCheck( ) {
var _default = [undefined, 0, false, null ],
_arg = arguments;
for( var x in _default ) {
x in _arg ? 1 : _arg[x] = _default[x];
}
console.log( _arg[0],_arg[1],_arg[2],_arg[3] );
}
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:
argCheck();
>>undefined 0 false null
as defined in our default array of arguments values.
However the following is still possible:
argCheck({})
>>Object { } 0 false null
argCheck({}, [])
>>Object { } Array [ ] false null
But regretfully not:
argCheck("a",,,22);
>>SyntaxError: expected expression, got ','
Which would otherwise be logging:
>>a 0 false 22
but that's in a better world!
However - for the original question - the topmost function will do just fine.
e.g.:
function argCheck( arg, opt ) {
1 in arguments ? 1 : opt = "default";
console.log( arg, opt );
}
p.s.: sorry for not preserving the types of chosen defaults in my argument inputs while writing them.