0

I did a little research, and the best answer I found is: function overloading in js

Top 10 answers did gave me some hints and clues, but not the consistent way how to handle those situations in general.

Let's take a question a little further:

What if I am making API for someone else. That should give you the answer to following questions:

  • Why am I doing this?
  • JS doesn't have overriding in strict sense (yes I am aware, not the point)
  • Pass the object with optional parameters (Would prefer it, it's not up to me)
  • Specific solutions that assume types, fixed number of parameters, single values etc.

Some of the functions have to take many optional parameters (and some non-optional ones). So the function looks something like:

var f = function (unopt1, unopt2, op1, op2, op3) {
 // code
}
  • The unoptX parameters are not optional.
  • The opX parameters are optional (in a sense they can be equal to 1 value from fixed set or values or not passed to function at all).

So function can be called in any of the following ways:

f("z", "b")
f("a", "b", 1, "ff");
f("a", "b", "ff", "hic");
f("a", "b", "ff", "no-hic");

etc.

Obviously, optional parameters each can have certain values, let's say they are listed in a certain order. And ofc. function behaves differently depending on the parameters

What would be your reccomended approach on this? Multiple ones are fine, prefferably you will point out what are ups/downs of certain approach over the other.

Community
  • 1
  • 1
DanteTheSmith
  • 2,937
  • 1
  • 16
  • 31
  • 7
    Pass an object as parameter. The sequence and optional issue is solved. **ES6:** Use default parameters. – Tushar Aug 11 '16 at 15:49
  • As I mentioned, it's not up to me. I would prefer that solution (it's JS way of handling things - object literals) but it's not up to me. API has to work the way I described it. – DanteTheSmith Aug 11 '16 at 15:51
  • 1
    Just use a switch statement. Or a library that does multimethods. Heck. I even wrote one (shameless plug) https://github.com/jasmith79/js-typed – Jared Smith Aug 11 '16 at 15:51
  • I don't understand the question? You have an API that is already working? You wonder how to best call the functions in the API? Or what is your question? – trincot Aug 11 '16 at 15:54
  • 1
    Your question is one of best API design, when the API's design requirements have been stamped out very explicitly. You can either contest the design with its author and give reasons why it's poorly designed or not extensible, or write it based on the design. I'm not sure what you're asking in terms of "approach". – Katana314 Aug 11 '16 at 15:56
  • No, I am supposed to make API that provides that. I am the one writing the f function in question. And the requirement is that it behaves the way I described. It has to take some number of parameters that are fixed and they will be passed, and has to support several options. – DanteTheSmith Aug 11 '16 at 15:58
  • I am asking what is recommended way someone would handle it. I do have one that will surely work in mind (a cascade that starts at first optional element and checks if its value is from the list of values it can have, then if not if he is any of the values next optional parameter can have and so on till the last one). Repeat the procedure for each of the optional parameter. But it sounds terrible, and searching trough both here and google I didn't found better approach that will work in this specific case :( – DanteTheSmith Aug 11 '16 at 16:09
  • 1
    @DanteTheSmith That actually sounds like the best approach for this design. Keep in mind that anytime the possible set of values intersects in the slightest way, you *won't* be able to figure out which is which. Also, if it helps your method, you can use the keyword `arguments` to view all the arguments to the function as an array-like object. – Katana314 Aug 11 '16 at 16:31
  • Yap I realize that. Luckily it's specific keywords that all differ from each other. It is somewhat similar to a builder pattern, and the function builds itself depending on the parameters. BUT the last time I had to implement something like that, was in Java 7. And there I had a full power of OO available. As for JS, I improved upon beforementioned solution by having an array of all possible values, and another array of attribute names. I iterate trough arguments and whenever I hit a value I look to second array on the same index, holding argument name and bind that value to this.argumentName. – DanteTheSmith Aug 11 '16 at 17:12

2 Answers2

4

Use the spread operator as the argument:

function f(...args){
  switch(args.length){
    case 1:
    get()
    case 2:
    set()
    default:
    setWithOptions()
  }
}
jshawl
  • 3,315
  • 2
  • 22
  • 34
  • This doesn't solve all my problems (since it's not only a question of setting defaults) but it's a remarkably nice feature I would like to see in JS. And I was not aware if its existence, so you get an upvote! – DanteTheSmith Aug 11 '16 at 16:20
  • 1
    If you don't have ES2015 features available, you can accomplish the same with `Array.prototype.slice.call(arguments).length` – MaxPRafferty Aug 11 '16 at 21:58
1

Use an "options" object or ES6 "rest parameters"

var f = function (unopt1, unopt2, opts) {

  opts = opts || {};

  // later... if( opts.yourOptionalArg )

}

ES6 Rest Parameters

var f = function (unopt1, unopt2, ...args) {

  console.log(args)

  var firstOptionalArg = args[0];

}
Kevin Jantzer
  • 9,215
  • 2
  • 28
  • 52