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