-
-
Save cowboy/d59b3adfd906d1fcd597 to your computer and use it in GitHub Desktop.
// You can have multiple optional arguments, but only if the arguments | |
// can be distinguished from one another (in this example, by type) | |
function optionalUnambiguous(myString, myNumber) { | |
if (typeof myString === 'number') { | |
myNumber = myString; | |
myString = null; | |
} | |
if (myString == null) { myString = 'default'; } | |
if (myNumber == null) { myNumber = 0; } | |
return [myString, myNumber]; | |
} | |
optionalUnambiguous() // ["default", 0] | |
optionalUnambiguous('test') // ["test", 0] | |
optionalUnambiguous(123) // ["default", 123] | |
optionalUnambiguous('test', 123) // ["test", 123] | |
// What happens when you can't distinguish between the optional arguments? | |
// You run into problems! | |
function optionalAmbiguous(myValue1, myValue2) { | |
if (arguments.length === 1) { | |
// which value did they pass in: myValue1 or myValue2? | |
} | |
} | |
// Instead of a single function with multiple optional arguments, why not | |
// specify a series of functions that each accept a single argument? This | |
// way there's no possible ambiguity. | |
// | |
// I guess I've finally found a use case for currying in JavaScript! | |
// http://benalman.com/news/2012/09/partial-application-in-javascript/ | |
function optionalWhatever(myValue1) { | |
if (myValue1 == null) { myValue1 = 'default1'; } | |
return function(myValue2) { | |
if (myValue2 == null) { myValue2 = 'default2'; } | |
return [myValue1, myValue2]; | |
} | |
} | |
optionalWhatever()() // ["default1", "default2"] | |
optionalWhatever('test')() // ["test", "default2"] | |
optionalWhatever()(123) // ["default1", 123] | |
optionalWhatever('test')(123) // ["test", 123] |
Poured over the example trying to see if I would like the technique. But I'm not completely sold on this technique for implementing optional parameters. Typically I would use optional parameters when I want to enhance an already existing function or have flexibility down the road to add more parameters. But if had an existing function and I wanted to add another optional parameter all the existing calls would have to change to call the function twice.
1st draft:
exampleFx : function(foo) {
Return [foo];
}
exampleFx(‘1stDraft’);
// next I decide I want to extend this function to accept an additional optional parameter:
exampleFx : function(foo) {
return function(bar) {
return [foo, bar];
}
}
exampleFx(‘1stDraft’); // this version of the function no longer returns the array and instead returns a function. To get the array I have to call the returned function.
Since the order of the arguments still matter in this example
optionalWhatever()() // ["default1", "default2"]
optionalWhatever('test')() // ["test", "default2"]
optionalWhatever()(123) // ["default1", 123]
optionalWhatever('test')(123) // ["test", 123]
I don't quite see how it's that much better than optionalWhatever(null, "test")
, etc.
or am I missing something?
For full credit I'm going to need a single example in which this improves the clarity of an API.