1
\$\begingroup\$

I've got a simple JavaScript function that takes multiple types of arguments. Inside the function I'm doing a check on the arguments to determine which way the user called the function:

var build = function() {
    var args = Array.prototype.slice.call(arguments)
    var options = {
        to: {},
        from: {},
        relationship: null
    }

    if (_.isString(args[3]) && !_.isUuid(args[3]) && _.isString(args[4])) {
        options.to.type = args[3]
    } else if (_.isString(args[2]) && !_.isUuid(args[2]) && _.isString(args[3])) {
        options.to.type = args[2]
    }
}

// called like:
build(client, dataObj, 'relationship', 'type', 'name')
// or
build(client, dataObj, 'relationship', '<uuid>')

This looks messy and isn't really scalable. Is there a more succinct way I can write this (perhaps using .map(), .filter(), or .reduce())?

\$\endgroup\$
  • 1
    \$\begingroup\$ This looks hypothetical to me. to.type? args? Is this real code, or is this example code? \$\endgroup\$ – SirPython Jan 5 '16 at 0:08
  • \$\begingroup\$ Real code. args being an array of arguments to the function from Array.prototype.slice.call(arguments). \$\endgroup\$ – brandonscript Jan 5 '16 at 1:31
  • \$\begingroup\$ Okay. However, as it stands, it looks hypothetical. Perhaps if you included more code, such as (at least) the beginning of the function along with this options object, you may see some better feedback. \$\endgroup\$ – SirPython Jan 5 '16 at 1:37
  • \$\begingroup\$ Alright, I did that. Frankly it's not a difficult bit of code, I just would like to write it more cleanly if there's a way. \$\endgroup\$ – brandonscript Jan 5 '16 at 1:42
  • \$\begingroup\$ Thanks! Your post looks much better now. I understand its fairly simple code, but if we see the full scope, perhaps better alternatives can be proposed. \$\endgroup\$ – SirPython Jan 5 '16 at 1:44
2
\$\begingroup\$

Define the functions that correspond to a given argument configuration separately:

const processStringNumber = (string, number) => console.log(number + ' is a number')
const processStringString= (string, string2) => console.log(string2+ ' is a string')

Put the argument configurations and the corresponding functions in a data structure:

const processingObj = [
  {
    argsTypes: ['string', 'number'],
    process: processStringNumber
  },
  {
    argsTypes: ['string', 'string'],
    process: processStringString
  }
]

Write a helper that does the checks and dispatches the corresponding function:

//Retrieve the types of an array of args (can have different implementations)
const getTypes = (args) => args.map((arg) => typeof arg)

//Calls the appropriate function from 'processingObj'
const process = (args, processingObj) =>
  processingObj
    .find((process) => _.isEqual(process.argsTypes, getTypes(args)))
    .process(...args)

Usage:

process(["aaa", 1], processingObj) // 1 is a number
process(["aaa", "aaa"], processingObj) // aaa is a string

Here is also an ES5 version (via Babel)

\$\endgroup\$
  • \$\begingroup\$ Thanks Bobby - would be great to have a non ES6 option too? \$\endgroup\$ – brandonscript Jan 5 '16 at 14:52
  • \$\begingroup\$ Added a comment \$\endgroup\$ – Bobby Marinoff Jan 5 '16 at 15:10
  • \$\begingroup\$ Nice! Thanks a lot. I like that solution. \$\endgroup\$ – brandonscript Jan 5 '16 at 15:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.