I ran into an interesting quirk with JavaScript yesterday, one I’m surprised I hadn’t noticed before. JavaScript does not allow you to give arguments default values when defining functions. So after a bit of tinkering, I came up with a solution.
function lorum(x, y) { if(typeof(x) == "undefined") { x = 100; } if(typeof(y) == "undefined") { y = 500; } // ... }
Of course you could use a ternary operator if you prefer, however I know I’m not alone when I say that I do not like them. In any case, here’s an example using them:
function ipsum(i, j) { i = typeof(i) == "undefined" ? 100 : i; j = typeof(j) == "undefined" ? 500 : j; // ... }
Despite its reduced code space, I prefer not to use them as they can be confusing at first glance. But to each his own.
A seasoned Senior Solutions Architect with 20 years of experience in technology design and implementation. Renowned for innovative solutions and strategic insights, he excels in driving complex projects to success. Outside work, he is a passionate fisherman and fish keeper, specializing in planted tanks.
Two things. Undefined evaluates to false in an if statement and if statements can be put on a single line — with the proviso that the code executed in the positive case only takes up one line. This means you can set default values like this:
if (!x) x = 100;
if (!y) y = 500;
Or even shorter:
i = i || 100;
j = j || 500;
What are the drawbacks to checking whether the variable exists more directly with:
function ipsum(i, j) {
i = i === undefined ? 100 : i;
j = j === undefined ? 500 : j;
// …
}
In fact, you can shorten that in Javascript to:
i = i || 100;
j = j || 500;
If i or j is meant to be set to 0 by the end-user, this code will not allow that:
function tell_it(i, j){
i = i === undefined ? 100 : i;
j = j === undefined ? 500 : j;
system.k7.shell.print(i);
system.k7.shell.print(j);
}
function say_what(i, j){
i = i || 100;
j = j || 500;
system.k7.shell.print(i);
system.k7.shell.print(j);
}
system.k7.shell.print(‘—– say what’);
say_what();
say_what(1, 2);
say_what(0, 3);
system.k7.shell.print(‘—– tell it’);
tell_it();
tell_it(1, 2);
tell_it(0, 3);
Outputs:
$ k7 js_is_cool.js
—– say what
100
500
1
2
100
3
—– tell it
100
500
1
2
0
3
If i or j is meant to be set to 0 by the end-user, this code will not allow that:
function tell_it(i, j){
i = i === undefined ? 100 : i;
j = j === undefined ? 500 : j;
system.k7.shell.print(i);
system.k7.shell.print(j);
}
function say_what(i, j){
i = i || 100;
j = j || 500;
system.k7.shell.print(i);
system.k7.shell.print(j);
}
system.k7.shell.print(‘—– say what’);
say_what();
say_what(1, 2);
say_what(0, 3);
system.k7.shell.print(‘—– tell it’);
tell_it();
tell_it(1, 2);
tell_it(0, 3);
Outputs:
$ k7 js_is_cool.js
—– say what
100
500
1
2
100
3
—– tell it
100
500
1
2
0
3
You should be declaring your variables with var inside the function, otherwise you’re creating global variables and are much more likely to have name collisions. vars inside a function are “private”, a variable declared within a function is not accessible outside of that function.
function ipsum(i, j) {
var i = i || 100;
var j = j || 500;
// or in one var declaration
var i = i || 100, j = j || 500
}
The typeof === undefined comparision is better as it will not cause problems with boolean (or falsey) parameter values.
function foo(flag){
return flag || true;
}
flag(true) == flag(false) == flag();
a corner case for sure, but certainly a failure case for the boolean operand strategy
oops…
function flag(flag){
return flag || true;
}
flag(true) == flag(false) == flag();
Ah, very good point; I hadn’t thought of that. Thank you.
IMO it is more readable/understandable to use the “arguments” variable and it allows more flexibility. Something like:
function lorum(/*x, y*/) {
var x;
var y;
switch(arguments.length) {
case 0 :
x = 100;
y = 500;
break
case 1 :
x = arguments[0];
y = 500;
break
case 2 :
x = arguments[0];
y = arguments[1];
break;
}
// …
}