Reputation: 6613
say I have this
function isdef(x) { return typeof x !== 'undefined'; }
function banana(a, b, c) {
if (!isdef(a)) a = 1;
if (!isdef(b)) b = 2;
if (!isdef(c)) c = 3;
...
}
So all of the arguments are optional. If I want to call it with just c argument I'd have to write
banana(undefined, undefined, 5);
which is kinda clunky.
Sure I could do something like
window.k = undefined;
...
banana(k, k, 5);
But I'd really rather not make short window scope variables.
In vb.net for example, I could write
banana(,,5)
but js doesn't like that.
Is there a convenient way to do skip an argument in a function call?
Upvotes: 0
Views: 109
Reputation:
Is there a convenient way to skip an argument in a function call?
Not directly.
This topic was discussed on the ES Discuss mailing group. The reception to that proposal was frosty, to say the least. It was also suggested to make parameters in function definitions optional:
function foo(a, , b) { }
Your options include:
Using spread syntax as follows:
banana(...[,,5])
Re-order the parameters to put the optional ones at the end.
Write a higher-level function which transforms functions to add additional leading arguments:
function prefixArgs(fn, n) {
return function(...args) {
return fn(...Array(n), ...args);
};
}
prefixArgs(banana, 2)(5)
Use an object instead of a list of parameters, as suggested in other answers.
"Curry" the function, as
function banana(a = 1) {
return function(b = 2) {
return function(c = 3) {
return SOMETHING-USING-A-B-AND-C;
};
};
}
banana()()(5)
Notice that in the above I've used parameter defaults. They're a good alternative to the checks you wrote for undefined:
function banana(a = 1, b = 2, c = 3) {
...
}
although this itself does not solve the problem of how to pass in leading optional parameters. You can use this implementation of banana
in conjunction with some of the ideas above.
Support. Note that spread parameters and parameter defaults are ES6 features. If you're not familiar with them, you should start learning about them. If you need to target browsers such as IE which don't support them natively, then you'll need to transpile using well-known tools such as Babel.
Upvotes: 1
Reputation: 1
You could use rest parameter
, Array.prototype.map()
, bracket notation. Pass index to select as first parameter to banana
or null
if all variables should be returned
function isdef(x) {
return typeof x !== 'undefined';
}
function banana(i, ...args) {
var res = i ? [!isdef(args[i])] : args.map(value => !isdef(value));
return res.length === 1 ? res[0] : res;
}
console.log(banana(2, undefined, undefined, 5));
console.log(banana(null, undefined, undefined, 5));
Upvotes: 0
Reputation: 332
I think there is no way in JavaScript you can only provide the later arguments without passing the first arguments. And I'm not sure about your requirements. But here is my approach. Please feel free to reply.
function banana(bananaObj){
bananaObj = bananaObj || {};
bananaObj.a = bananaObj.a || 1;
bananaObj.b = bananaObj.b || 2;
bananaObj.c = bananaObj.c || 3;
document.write('bananaObj: ', JSON.stringify(bananaObj));
}
banana({c:10})
Upvotes: 1
Reputation: 4423
You can declare required arguments first, and followed by optional arguments in this way:
function banana(a, b, c) {
b = b || 0;
c = c || 0;
// a is required, b and c is optional, either b or 0
}
Call the function banana(1)
which omits b
and c
, or provide all the argument banana(1, 2, 3)
.
Another method is to declare arguments to a object so that you don't need to remember the order or the number of your arguments.
function banana(args) {
// set defaults
args.a = args.a || 0;
args.b = args.b || 0;
args.c = args.c || 0;
}
Call the function banana({ a: 1, b: 2 })
.
Upvotes: 0
Reputation: 4859
you can pass an object instead
function banana(options) {
if (!isdef(options.a)) a = 1;
if (!isdef(options.b)) b = 1;
}
banana({a:1});
Upvotes: 2