Search code examples
javascriptjqueryparametersparameter-passingsinemacula

Extending function parameters based on parameter type


Explanation

I have a function that is passed the parameter options. This parameter can either be an object, array or string. Depending on what the parameter is, will determine what to do.


UPDATE: I forgot to mention that, options must always end up as an object of the same structure (in other words, it must always have the default values set).

I only want to define the default values once so using procedural if statements as some of you have suggested is not my preferred solution, but I will resort to it if necessary.

I do not want to do this (if possible):

function foo(options){
    switch(typeof options){
        case 'string':
            // do something etc
        break;  
        // etc
    }
}

Example

If the parameter is an object, then extend it to set the defaults like so:

function foo(options){
    // Extend the options to apply default values
    var options = $.extend({
        bar: 'none',
        baz: []
    },options);         
}

If the parameter is a string then set the options.bar to equal the string and extend the default values (something like this):

function foo(options){
    // Set the bar property to equal the supplied string
    var options = {
        bar: options    
    };
    // Extend the options to apply default values
    options = $.extend({
        baz: []
    },options);         
}

If the parameter is an array then set the options.baz to equal the array, and extend the default values (something like this):

function foo(options){
    // Set the baz property to equal the supplied array
    var options = {
        baz: options    
    };
    // Extend the options to apply default values
    options = $.extend({
        bar: 'none'
    },options);         
}

Question

So effectively, I want to be able to supply a parameter in any format, and the function will build the same options object from what has been supplied. If the values have not be supplied then they resort to their default values.

Sorry this is so unclear, it is very hard to explain.

Additional Example

Another potential way I (jQuery) can demonstrate is by looking at a function like animate(). Notice that you can either supply:

.animate( properties [, duration] [, easing] [, complete] )

or

.animate( properties, options )

This additional example is not exactly what I am hoping to achieve but it is along the right lines


Solution

  • You can use various jQuery helper functions to determine the type of options:

    $.isPlainObject(options)
    $.isArray(options)
    

    and

    typeof options === "string"
    

    e.g.

    function foo(par) {
    
        // default values
        var options = {
            bar: 'none',
            baz: []
        };
    
        if ($.isPlainObject(par)) {
            $.extend(options, par);
        } else if ($.isArray(par)) {
            options.baz = par;
        } else if (typeof options === "string") {
            options.bar = par;
        }
    
        ...
     }
    

    If you intend to change any of those values, use .slice() for array copies, and the deep-copy option on $.extend() so that changes don't affect the object that was supplied.

    UPDATED ANSWER

    For this particular case, the answer is:

    function foo(parameter){
        var options = {
            package:    'none', // Do not load any packages by default
            packageURL: false, // Do not retrieve the package details from a URL by default
            libraries:  [] // Do not load any libraries by default
        };
        // Determine the type of parameter supplied and 
        // build the options accordingly
        if($.isArray(parameter)){
            // Set libraries option
            parameter = {
                libraries: parameter    
            };
        }else if(typeof parameter === "string"){
            // Set package option
            parameter = {
                package: parameter  
            };
        }
        // Extend the parameter object to include the default values
        $.extend(options, parameter);
    }