In many other interpreted programming languages like: Python, PHP, ActionScript 3.0, etc., you can have defaults to arguments that do not get passed to functions. In the three a fore mentioned languages, it's as easy as saying arg = 'default' inline in the function definition. This however is not available in the JavaScript interpreter. (It might be in ECMAScript 5, though.) But that can easily be remedied with a simple helper function.
I have met other programmers that find it ridiculous that you have to create features in JavaScript that are built into other languages. They use that to put down JavaScript and call it a terrible language. However, I think that's part of what makes JavaScript so great. JavaScript, though not as powerful in features as some other languages, offers enough flexibility and expressiveness that you can create what you feel that you are missing. Lets take a look at the problem and see how easy we can remedy it.
First, look at a basic function that is about the same in most C based languages:
function foo(arg1, arg2)
{
return arg2;
}
foo('one', 'two'); // returns 'two'
foo('one'); // undefined
In the above example, you MUST have a second argument passed to the function, or you get an error. Some people remedy that like so:
function foo(arg1, arg2)
{
//check for defaults
var arg1 = arg1 || "one";
var arg2 = arg2 || "two";
return arg2;
}
foo('one', 'also two'); // returns 'also two'
foo('one'); // returns 'two'
The above works OK, but is a little cumbersome. The logical or operator or '||' (double pipe) in JavaScript returns the first item if it is truthy, or the second item no matter what. Usually, you'll only see that in if statement blocks, but this idiom works well as an either or return value and is used such. NOTE: This idiom would not work well with any value passed that is falsey: A blank string, an integer 0, boolean false, etc., because it returns the second item when the first argument is a falsey value and not just undefined or null.
The above fix is lousy, though, because it becomes a mess when you have more than one optional argument. Take the following example that uses an object literal as the only argument and allows for passing only the arguments you want to send:
function foo(args)
{
//check for defaults
args.arg1 = args.arg1 || "one";
args.arg2 = args.arg2 || "two";
args.arg3 = args.arg3 || "three";
return args.arg2;
}
foo({"arg2":"also two"}); // returns 'also two'
foo({"arg1":"also one"}); // returns 'two'
The above works a little better because it allows you to pass only the arguments you want without having to null out others. It still presents ugly default checking and the same issues with falsey statements. We can use the same idea, but implement it far better with a simple function that will take a set of defaults and replace passed items over it and return the a useable object with all defaults and arguments in one.
function defaults(def, arg)
{
for(var i in arg)
{
def = arg;
}
return def;
}
The above code takes exactly two arguments, the first being an object with the default 'name:value' pairs for your arguments. The second one is the argument object actually passed to the defaults function. The second object is iterated over and all of its values are placed over the default ones and the default object is returned. This will give a usable object with defaults in place and actual passed arguments where presented.
How it actually works can be displayed as such:
| Defaults Object | Arguments Object | Resulting Object |
|---|---|---|
| "one" | (nothing passed) | "one" |
| "two" | "also two" | "also two" |
| "three" | (nothing passed) | "three" |
Lets see it in action:
function foo(args)
{
args = defaults({
arg1 :"one",
arg2 :"two",
arg3 :"three"
}, args);
return args.arg2;
}
foo({"arg2":"also two"}); // returns 'also two'
foo({"arg1":"also one"}); // returns 'two'
The default arguments are much less cluttered and were properly applied to items missing from the passed args object. Armed with our new defaults function and knowledge of how to use a single object to send all arguments, we can now safely send only select arguments, falsey or not, and have default arguments take care of the rest.
Enjoy!