user81993
user81993

Reputation: 6613

any shorter way of skipping a function argument than writing out undefined?

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

Answers (5)

user663031
user663031

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:

  1. Using spread syntax as follows:

    banana(...[,,5])
    
  2. Re-order the parameters to put the optional ones at the end.

  3. 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)
    
  4. Use an object instead of a list of parameters, as suggested in other answers.

  5. "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

guest271314
guest271314

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

Mahavir
Mahavir

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

WangYudong
WangYudong

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

monkeyinsight
monkeyinsight

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

Related Questions