1

I have a function with variable arguments, similar to that

function fn(...args) {
    let str, arr, obj;

    if (args.length == 1) {
        if (typeof args[0] == 'object') {
            obj = args[0];
        } else {
            str = args[0];
        }
    } else if (args.length == 2) {
        str = args[0];
        if (typeof args[1] == 'object') {
            obj = args[1];
        } else {
            arr = args[1];
        }
    } else if (args.length == 3) {
        [str, arr, obj] = args;
    }
}

And the API is

fn()
fn(String str)
fn(Object obj)
fn(String str, Array arr)
fn(String str, Object obj)
fn(String str, Array arr, Object obj)

It is intentionally loose on types (e.g. some arguments may be undefined).

It is browser code, quite compact. It is certainly doable this way but are there better recipes, less verbose and more maintainable? Any Node or generic JS libraries that are able to do the dirty job while staying modest in footprint and dependencies?

6
  • Sorry, and just why do you think this an acceptable question? It is way too broad. Just because something is a question does not automatically mean that it is allowed here. At 3k rep you should know what questions are OK by now. Commented Oct 4, 2015 at 23:13
  • @JK What are your personal recommendations on improving the question? I'm quite sure that 'too many possible answers, or good answers would be too long' isn't the case. Good answers that can keep me from reinventing the wheel exist, and there won't be too much of them. Commented Oct 4, 2015 at 23:31
  • Nothing to do with the question, but this won't work the way you think it will: if (typeof args[1] == 'object') { obj = args[1]; } else { arr = args[1]; }, since typeof an Array is also 'object'. Commented Oct 4, 2015 at 23:32
  • @Buzinas ah thx for pointing that out. I hadn't considered that as an added complication for writing a function like this. Commented Oct 4, 2015 at 23:40
  • @Buzinas Good one, I would certainly forget about that. Right now I'm looking at how gracefully jQuery deals with types and it makes me think that sticking to third-party solution would be a wise choice, if there are any. Commented Oct 4, 2015 at 23:48

1 Answer 1

2

The "problem" I see with this is that not only are you overloading with variadic arguments, you're overloading argument types as well. The combination leads to a messy implementation which only hurts you in the long run.

Here's a different way to write it that uses an auxiliary function, but you're still in for a world of pain (more below).

function fn(...args) {
    function aux(str, arr, obj) {
       // this function will always have str, arr, and obj
    }

    // Warning: this has an error anyway because (typeof []) is also 'object'

    switch (args.length) {
      case 1: return typeof args[0] === 'object'
                ? aux(null, null, args[0])
                : aux(args[0], null, null);

      case 2: return typeof args[0] === 'object'
                ? aux(args[0], null, args[1])
                : aux(args[0], args[1], null);

      case 3: return aux(args[0], args[1], args[2]);
    }


}

With the above implementation, you have 5 unique ways to call your function, all of which are intended to be acceptable and appropriate.

Cons

  1. Hard-to-memorize API - which result will I get based on which arguments? When I pass a string and an object, which one do I pass first? etc.
  2. Refactor nightmare - If the function ever needs to change, you need to support all 5 varieties of calls. Once you've forced all 5 behaviours through a single function api, there's no way to separate behaviours without breaking existing code written against this function.
  3. Unusually complicated boiler plate in function definition - Most functions just map arguments to their local parameters and that's all taken care of for you by JavaScript itself. Your function now has a bunch of code change the way JavaScript behaves, and your code readability suffers because of it. This boilerplate will be multiplied for each function you write with this sort of "design".
  4. Hard-to-detect types - typeof [] will return 'object' not 'array' like you might be thinking. You're going to have to write tons of corner cases to ensure you're detecting all of your types correctly. JavaScript is not a typed language, and therefore trying to negotiate behaviour based on typeof as your go-to detection mechanism is going to lead to all sorts of headaches. All this extra code means more probability for bugs, more code to maintain, and the overall quality of your software will ultimately suffer.

Pros

  1. this section intentionally left blank

Developers often make the mistake that because a language permits a certain way of thinking, that whatever code they come up with, as long as it compiles/executes, that it's OK.

This is a very big misconception, and often why experienced developers appreciate/favour a language with more strictness and more limitations.

Anyway, good luck.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.