Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@abozhilov
Created November 2, 2011 12:32
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save abozhilov/1333507 to your computer and use it in GitHub Desktop.
Save abozhilov/1333507 to your computer and use it in GitHub Desktop.
Arguments default value
function func(a, f) {
return function (args) {
args.__proto__ = a;
f.call(this, args);
};
};
var f = func({foo : 10, bar : 20}, function (args) {
print(args.foo, args.bar);
});
f({}); //10 20
f({foo : 50}); //50 20
f({foo : 50, bar : 50}); //50 50
@ryanflorence
Copy link

should be named "options" or "settings" default value. Args default value implies you don't have to pass in the arg.

function foo (arg1) {
  arg1 = (arg1 || (arg1 = true));
}

@YmMot
Copy link

YmMot commented Nov 2, 2011

@rpflorence , || etc return the last expression they evaluate so you can just write

function foo ( arg1 ) {
    arg1 = arg1 || true;
}

Though note, this method assumes you want truthy values to be valid and falsey values to be invalid...or that the only valid falsey value is the default... which is not always the case. For example, 0 might be a valid value but this would toss it and use the default.

So perhaps:

function foo ( arg1 ) {
    arg1 = isValid( arg1 ) ? arg1 || default_value;
}

Where isValid is a function that makes sure arg1 is suitable.

@abozhilov :

Overall I think this example is over-convoluted for little benefit. More importantly proto is not supported by all browsers.

If a function only has a couple arguments, I use the technique just demonstrated. If it has a lot, I have it accept an object containing various options, and then maybe use a function like the following:

function setOptions( user_options ) {
  var option   = null
     ,no_opt   = null
     ,defaults = default_options
  ;

  for ( option in defaults ) {
    no_opt = defaults.hasOwnProperty( option ) &&
              !user_options.hasOwnProperty( option );
    if ( no_opt ) {
      user_options[ option ] = defaults[ option ];
    }
  }
  return user_options;
}

This will take the options object provided by the function and fill in any missing options from an object containing defaults.

Another options is to use CoffeeScript which makes the whole thing much cleaner:

foo = ( bar = "blah", buzz = "fizz" ) ->
    console.log bar, buzz

@ArtS
Copy link

ArtS commented Nov 3, 2011

@YmMot , while .proto is not available in all browsers, .prototype should be?

@abozhilov
Copy link
Author

@YmMot your function is OK, but the main drawback is that I have to put that code in the body of function. The idea of my pattern was to keep clean function's body. The main benefit is clever code, especially for the reader. Some people told me that __proto__ is not good for performance. While I agree with that statement, I totally disagree with function like that should be used in performance critical moment. In performance critical moment we usually use optimized functions which haven't default argument values.

Regarding __proto__, yes it's non-standard mimic of internal [[Prototype]]. Instead of __proto__ you can use Object.create to create fresh object which inherits from default arguments object and then augment with properties of passed args objects. This would work everywhere. If someone is interested in cross browser solution, I'm able to post it.

The cross browser solution is available: https://gist.github.com/1336141

@YmMot
Copy link

YmMot commented Nov 6, 2011

@ArtS, they are not interchangeable in this instance.

@abozhilov

The idea of my pattern was to keep clean function's body.

In both my examples, you're only adding one line of code really. They're also very explicit about what they're doing.

I would argue that your function is less explicit and actually makes things much messier; by either creating a lot of noise at the point of function creation or clouding how the code works by decorating the function later on.

In the case of the former, you're now dealing with anonymous functions which make your stack traces less readable. Decorators are fine in principle, but in this case I just don't see the benefit. Obviously coders should use what they find most readable.

I do think this would be good for partial function application, or for modifying an existing function to take an object of arguments, etc.... I just don't think this should be used for giving functions default arguments and it definitely needs a more descriptive name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment