Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unordered function arguments in Javascript

Below is a regular function with named parameters:

function who(name, age, isMale, weight)
{
    alert(name + ' (' + (isMale ? 'male' : 'female') + '), ' + age + ' years old, ' + weight + ' kg.');
}

who('Jack', 30, true, 90); //this is OK.

What I want to achive is; whether you pass the arguments in order or not; the function should produce a similar result (if not the same):

who('Jack', 30, true, 90); //should produce the same result with the regular function
who(30, 90, true, 'Jack'); //should produce the same result
who(true, 30, 'Jack', 90); //should produce the same result

This enables you to pass a list of arguments in any order but still will be mapped to a logical order. My approach up to now is something like this:

function who()
{
    var name = getStringInArgs(arguments, 0); //gets first string in arguments
    var isMale = getBooleanInArgs(arguments, 0); //gets first boolean in arguments
    var age = getNumberInArgs(arguments, 0); //gets first number in arguments
    var weight = getNumberInArgs(arguments, 1); //gets second number in arguments

    alert(name + ' (' + (isMale ? 'male' : 'female') + '), ' + age + ' years old, ' + weight + ' kg.');
}

There is a little problem here; functions such as getStringInArgs() and getNumberInArgs() go through all the arguments each time to find the arg by type at the specified position. I could iterate through args only once and keep flags for the positions but then I would have to do it inside the who() function.

Do you think this approach is logical and the only way? Is there a better way to do it?

EDIT 1: Code above actually works. I just want to know if there is a better way.

EDIT 2: You may wonder if this is necessary or whether it makes sense. The main reason is: I'm writing a jQuery function which adds a specific style to a DOM element. I want this function to treat its arguments like shorthand CSS values.

Example:

border: 1px solid red;
border: solid 1px red; /*will produce the same*/

So; here is the real and final code upto now:

(function($){
function getArgument(args, type, occurrence, defaultValue)
{
    if (args.length == 0) return defaultValue;

    var count = 0;
    for(var i = 0; i < args.length; i++)
    {
          if (typeof args[i] === type)
          {
              if (count == occurrence) { return args[i]; }
              else { count++; }
          }
    }
    return defaultValue;
}

$.fn.shadow = function()
{
    var blur = getArgument(arguments, 'number', 0, 3);
    var hLength = getArgument(arguments, 'number', 1, 0);
    var vLength = getArgument(arguments, 'number', 2, 0);
    var color = getArgument(arguments, 'string', 0, '#000');
    var inset = getArgument(arguments, 'boolean', 0, false);
    var strInset = inset ? 'inset ' : '';

    var sValue = strInset + hLength + 'px ' + vLength + 'px ' + blur + 'px ' + color;
    var style = {
        '-moz-box-shadow': sValue,
        '-webkit-box-shadow': sValue,
        'box-shadow': sValue
    };

    return this.each(function()
    {
        $(this).css(style);
    });
}
})(jQuery);

Usage:

$('.dropShadow').shadow(true, 3, 3, 5, '#FF0000');
$('.dropShadow').shadow(3, 3, 5, '#FF0000', true);
$('.dropShadow').shadow();
like image 455
Onur Yıldırım Avatar asked Dec 12 '22 10:12

Onur Yıldırım


2 Answers

I find using objects to be more straight-forward and less error prone in the future:

var person = {
 name: 'Jack',
 age: 30,
 isMale: true,
 weight: 90
};

who(person);

function who(person){
 alert(person.name + 
  ' (' + (person.isMale ? 'male' : 'female') + '), ' + 
  person.age + ' years old, ' +
  person.weight + ' kg.');
}

That way when you come back years later you don't have to lookup to see if age was the first, second, or fifth number and is more descriptive of what you are trying to accomplish.

like image 133
WSkid Avatar answered Dec 21 '22 04:12

WSkid


This seems unnecessarily complex, not just from the perspective of the function, which needs to reorder its arguments, but also from the perspective of whoever is calling. You say that the function can accept its paramters in any order, but that's not entirely true. Since your determination of which variable is which is based on type, it relies on each variable being a different type. The name and gender can be anywhere, but the numeric arguments have to be in a specific order. It also prevents someone from passing in "30" or "90", which are numbers but will be regarded as strings - confusing it with the name and not finding an age or weight.

like image 26
Dennis Avatar answered Dec 21 '22 04:12

Dennis