One problem though it that it's modifying the opts parameter so it might create unwanted side-effects.
var myopts = {foo: 1}
foo(myopts)
console.log(myopts) // => {foo: 1, bar: "baz"}As with _.extend, _.defaults takes 1..n arguments and will fold 2..n into 1. If you fear callers will pass in an object they rely on for function options (doubtful, but why not) you can just write:
var actual_opts = _.defaults({}, opts, {
// Your defaults here
});
where ``opts`` is the options object passed in.This also fixes the issue of a caller passing in no options (or "null" or "undefined") without having to add an `||`
zimbatm notes an issue with altering the object you're provided, but there's actually a bigger one with this method: if the function is called with no options or `null` or `undefined` it will blow up with a rather unhelpful message.
Unless you have a truly huge set of options, I'd suggest using
var final_opts = _.defaults({}, opts, defaults);
instead: `opts` being `null` or `undefined` will be equivalent to an empty object.This is a good point, and unfortunately it means that most of the advantage of using _.defaults() goes by the wayside. It just becomes a matter of personal preference. Thanks for the tip.
> This is a good point, and unfortunately it means that most of the advantage of using _.defaults() goes by the wayside.
How and why? I don't consider mutating the original object to be an advantage of using _.defaults, unless the object is completely under your control and you're essentially calling `_.defaults(this, defaults)`.
The advantage is, using _.defaults, that you aren't passing a defaults object around within the body of your method and using it as if it were the opts, or reassigning to yet another var (see `finalParams` defined in the last example). This makes the method a bit clearer.