There’s more than one way to skin a cat, and there’s more than one way to accept optional parameters. (Editors note: I do not condone skinning cats!)
Object
Coming from a Ruby background, I find this option the most intuitive. You can create an object of your optional parameters, it'd look something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var params = {
size: 'small',
color: 'red'
};
function carSentence(optionalParams) {
var size = optionalParams.size;
var color = optionalParams.color;
var speed = optionalParams.speed;
console.log("My favourite car is a " + size +
" sized " + color + " one that goes " + speed);
}
carSentence(params);
// logs "My favourite car is a small sized red one that goes undefined"
As you can see I didn’t supply the speed parameter in my params object, but the carSentence function still worked. So speed was an optional parameter.
But optionalParams was still required
Yep, you caught me! This isn’t really what people usually mean by “optional” parameters. But I did want to throw it out there as a possibility. I think it’s an underrated option.
What if I wanted a default speed?
optionalParams didn’t define a value for speed, but the sentence expected speed to be defined. In this case you can give a default value for the variable (such as "fast"). It’s tempting to do this:
1
var speed = optionalParams.speed || "fast";
but this won’t work when optionalParams.speed is false. The better way to handle it is:
1
2
3
4
var speed;
if (typeof optionalParams.speed === 'undefined') {
speed = "fast";
}
however that’s quite wordy. You can cut it down with a ternary, or make a givenOrDefault method (hopefully with a better name!).
1
2
3
4
5
6
7
function givenOrDefault(given, default) {
if (typeof given !== 'undefined') {
return given;
} else {
return default;
}
}
Thus our example becomes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var params = {
size: ’small',
color: 'red'
};
function carSentence(optionalParams) {
var size = givenOrDefault(optionalParams.size, "medium");
var color = givenOrDefault(optionalParams.color, "blue");
var speed = givenOrDefault(optionalParams.speed, "fast");
console.log("My favourite car is a " + size +
" sized " + color + " one that goes " + speed);
}
carSentence(params);
// logs "My favourite car is a small sized red one that goes fast"
Missing parameters
Another method of dealing with optional parameters is to simply allow them to be missing.
1
2
3
4
5
6
7
8
9
function carSentence(size, color, speed) {
size = givenOrDefault(size, "medium");
color = givenOrDefault(color, "blue");
speed = givenOrDefault(speed, "fast");
console.log("My favourite car is a " + size +
" sized " + color + " one that goes " + speed);
}
carSentence("medium", "blue");
// logs "My favourite car is a medium sized blue one that goes fast"
This way of dealing with optional parameters works well if people won’t bother trying to extend it past the limit. However, not all functions meet this requirement, consider the following:
1
2
3
4
5
6
7
8
9
10
function add(a, b, c) {
a = a || 0;
b = b || 0;
c = c || 0;
return a + b + c;
}
add(1, 2); // returns 3
add(1, 2, 3); // returns 6
add(1, undefined, 3); // returns 4
It kinda works. It'll fall over if you try add(1, 2, 3, 4) which returns 6 rather than 10.
arguments
Finally we come to the arguments keyword. it looks like this:
1
2
3
4
5
6
7
8
9
function carSentence() {
size = givenOrDefault(arguments[0], "medium");
color = givenOrDefault(arguments[1], "blue");
speed = givenOrDefault(arguments[2], "fast");
console.log("My favourite car is a " + size +
" sized " + color + " one that goes " + speed);
}
carSentence("medium", "blue");
// logs "My favourite car is a medium sized blue one that goes fast"
or like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function add() {
var sum = 0;
var index = 0;
while(index < arguments.length) {
if(typeof arguments[index] !== 'undefined') {
sum = sum + arguments[index];
}
index++;
}
return sum;
}
add(1, 2); // returns 3
add(1, 2, 3); // returns 6
add(1, undefined, 3); // returns 4
add(1, 2, 3, 4); // returns 10
What is this black magic?!
Well it turns out arguments is a secret variable available in all functions that gives a list of the parameters passed to that function. It’s a little bonus JS throws in free of charge.
So it’s an array of all the params
Almost. It’s not quite an array. It’s like a kiddy array - hasn’t got all the functionality just yet. If you want to use it for access only (as in the example above), then you're all good. But if you want to do interesting manipulations, pop things off, or reorder items, then you need to convert arguments to a full array:
1
var temp = Array.slice(arguments);
I assume the reason for this is to make arguments read only, although I haven’t researched that.
And there you have it - three ways to handle optional parameters in JavaScript.
Resources
- Stackoverflow
- Mark Hansen
- Arguments official
- Arguments this one is more entertaining