views:

30

answers:

3

It seems the best way to deal with arguments in javascript functions is to require the caller to pass an associative array:

example = function(options) {
  alert('option1: ' + options.a + ', option2: ' + options.b);
}

Now arguments are named and not needed in any particular order when calling this function:

example({'b':'hello option2', 'a':'hello option1'});

The only thing I don't like is I have to have all this extra code to deal with required and default arguments, not to mention not allowing extra arguments so the caller knows they called the function wrong:

example = function(options) {
var required_args = ['a', 'd'];
var default_args = {'b':'option2', 'c':'option3'};
var allowed_args = ['a', 'b', 'c', 'd'];
// check required args
// check allowed args
for (var arg in default_args) {
    if (typeof options[arg] == "undefined")
              options[arg] = default_args[arg];
  }
  alert('option1: ' + options.a + ', option2: ' + options.b);
}

Is there a standard way to deal with this? I guess I can create a function like:

deal_with_args(options, required_args, default_args, allowed_args)

And throw some exception if required_args or allowed_args is violated...

A: 

Could you do null coalescing for the required args?

alert('option1: ' + (options.a || default_args[a]) + ', option2: ' + (options.b || default_args[b]));

(Edited to correct the operator error)

Josh
javascript's "null coalescing operator" is not `??` it is `||`.
Dave
Yes I can do it this way too, but I think it's more readable my way above. I'm really looking for some standard way to deal with arguments like this..
at
+1  A: 
  1. Why do you want to have arguments in an arbitrary order? This is just confusing for people reading your code
  2. A function shouldn't have a lot of arguments - it's a hint that it is doing too much
  3. The usual pattern for 'required' and 'default' params doesn't seem so bad to me.

The 'standard' form is something like:

function myFunc(required_param, some_param, param_with_default) {
  // obviously this needs modifiction (ie use 'typeof' as you did) 
  // if you're dealing potentially 'falsey' values
  param_with_default = param_with_default || 'some default value';
  // same caution applies here
  if(!required_param) {
    // throw some exception here, or return an error code, or whatever
  }

  // function code
}
sje397
far more important than arbitrary order is named parameters for readability.
at
@at: Huh? In my example of a 'normal function', they _are_ named.
sje397
I was just answering your 1st point. But in your normal function the parameters are not named from the caller's perspective.
at
A: 

I think it can be valid to pass hashes of params to functions in javascript, particularly for constructors for UI components etc. In these cases you can sometimes end up with dozens of parameters for which need tweaking so I don't think it's always a bad idea to pass args as a hash.

In these cases I think it's smart to have a ready made hash of sensible defaults then extend it with your passed object.

I guess most people would do this with the extend method in their framework of choice (Object.extend(obj1, obj2) in prototype, jQuery.extend(obj1, obj2,...objn) etc. Under the hood these methods are just doing a for in and copying properties.

Ollie Edwards