Handling optional parameters in javascript

前端 未结 12 945
无人共我
无人共我 2020-11-28 19:19

I have a static javascript function that can take 1, 2 or 3 parameters:

function getData(id, parameters, callback) //parameters (associative array) and callb         


        
12条回答
  •  广开言路
    2020-11-28 20:00

    I know this is a pretty old question, but I dealt with this recently. Let me know what you think of this solution.

    I created a utility that lets me strongly type arguments and let them be optional. You basically wrap your function in a proxy. If you skip an argument, it's undefined. It may get quirky if you have multiple optional arguments with the same type right next to each other. (There are options to pass functions instead of types to do custom argument checks, as well as specifying default values for each parameter.)

    This is what the implementation looks like:

    function displayOverlay(/*message, timeout, callback*/) {
      return arrangeArgs(arguments, String, Number, Function, 
        function(message, timeout, callback) {
          /* ... your code ... */
        });
    };
    

    For clarity, here is what is going on:

    function displayOverlay(/*message, timeout, callback*/) {
      //arrangeArgs is the proxy
      return arrangeArgs(
               //first pass in the original arguments
               arguments, 
               //then pass in the type for each argument
               String,  Number,  Function, 
               //lastly, pass in your function and the proxy will do the rest!
               function(message, timeout, callback) {
    
                 //debug output of each argument to verify it's working
                 console.log("message", message, "timeout", timeout, "callback", callback);
    
                 /* ... your code ... */
    
               }
             );
    };
    

    You can view the arrangeArgs proxy code in my GitHub repository here:

    https://github.com/joelvh/Sysmo.js/blob/master/sysmo.js

    Here is the utility function with some comments copied from the repository:

    /*
     ****** Overview ******
     * 
     * Strongly type a function's arguments to allow for any arguments to be optional.
     * 
     * Other resources:
     * http://ejohn.org/blog/javascript-method-overloading/
     * 
     ****** Example implementation ******
     * 
     * //all args are optional... will display overlay with default settings
     * var displayOverlay = function() {
     *   return Sysmo.optionalArgs(arguments, 
     *            String, [Number, false, 0], Function, 
     *            function(message, timeout, callback) {
     *              var overlay = new Overlay(message);
     *              overlay.timeout = timeout;
     *              overlay.display({onDisplayed: callback});
     *            });
     * }
     * 
     ****** Example function call ******
     * 
     * //the window.alert() function is the callback, message and timeout are not defined.
     * displayOverlay(alert);
     * 
     * //displays the overlay after 500 miliseconds, then alerts... message is not defined.
     * displayOverlay(500, alert);
     * 
     ****** Setup ******
     * 
     * arguments = the original arguments to the function defined in your javascript API.
     * config = describe the argument type
     *  - Class - specify the type (e.g. String, Number, Function, Array) 
     *  - [Class/function, boolean, default] - pass an array where the first value is a class or a function...
     *                                         The "boolean" indicates if the first value should be treated as a function.
     *                                         The "default" is an optional default value to use instead of undefined.
     * 
     */
    arrangeArgs: function (/* arguments, config1 [, config2] , callback */) {
      //config format: [String, false, ''], [Number, false, 0], [Function, false, function(){}]
      //config doesn't need a default value.
      //config can also be classes instead of an array if not required and no default value.
    
      var configs = Sysmo.makeArray(arguments),
          values = Sysmo.makeArray(configs.shift()),
          callback = configs.pop(),
          args = [],
          done = function() {
            //add the proper number of arguments before adding remaining values
            if (!args.length) {
              args = Array(configs.length);
            }
            //fire callback with args and remaining values concatenated
            return callback.apply(null, args.concat(values));
          };
    
      //if there are not values to process, just fire callback
      if (!values.length) {
        return done();
      }
    
      //loop through configs to create more easily readable objects
      for (var i = 0; i < configs.length; i++) {
    
        var config = configs[i];
    
        //make sure there's a value
        if (values.length) {
    
          //type or validator function
          var fn = config[0] || config,
              //if config[1] is true, use fn as validator, 
              //otherwise create a validator from a closure to preserve fn for later use
              validate = (config[1]) ? fn : function(value) {
                return value.constructor === fn;
              };
    
          //see if arg value matches config
          if (validate(values[0])) {
            args.push(values.shift());
            continue;
          }
        }
    
        //add a default value if there is no value in the original args
        //or if the type didn't match
        args.push(config[2]);
      }
    
      return done();
    }
    

提交回复
热议问题