Optional Function Arguments in JavaScript

Many programming languages support optional function arguments - ie. functions in which certain arguments are optional. You can set a default value for any argument - so if the argument is not present, the default value will be used. Unfortunately, JavaScript is not one of these languages - so we will have to use a bit of trickery to get this effect in JavaScript.

In Other Languages

PHP is one of the languages that does this very well...

function myFunction($mandatory_argument,$optional_argument = 1) {
	/* ...Whatever... */
}

This don't need much explaining - the first argument is mandatory - you must provide it or the script will show an error. However, the second argument is optional. If you don't provide it, it will default to 1. If you did provide an argument, it will use that value.

This is the effect we want in javascript.

JavaScript Methods for Optional Arguments

In JavaScript, this effect can be mimicked using a number of ways...

Simple method

The simplest method of doing this is to check for the argument and create a new variable with the name of the argument if said argument is not present. This can be done in the following way...


function war(enemy,reason) {
	if(!enemy) { //The mandatory argument is not present - die with error(no pun intended)
		alert("Please choose an enemy before starting a war");
		return false;
	}
	if(!reason) { //If the optional argument is not there, create a new variable with that name.
		var reason = "They have Nukes!";
	}
	
	/* ...Do what you want with the arguments... */
}

This method is often seen in event handler functions - as some browsers provide the event as an argument of the function while others just set the global variable 'event'.

function doSomething(e) {
	if (!e) var e = window.event; //<-- see this part.
	alert(e.type);
}

Unlimited Arguments

Most of the time, we provide an argument list when declaring a function. But we can avoid that and create a function that will take unlimited number of arguments. These arguments can be accessed using the 'arguments' variable. You will understand this concept much easily if you have coded in Perl. In Perl this is the only way to create a function that can accept arguments. A javascript example illustrating this method is given below.

function accident() {
	for( var i = 0; i < arguments.length; i++ ) {
		alert("This accident was caused by " + arguments[i]);
	}
}
accident("me","a car","alcohol","a tree that had no right to be in the path of my driving");

You can assign a number to all needed arguments. If a argument is not present, use the default - like this...

function accident() {
	//Mandatory Arguments
	var driver = arguments[0];
	var condition = arguments[1]
	
	//Optional Arguments
	var blame_on = (arguments[2]) ? arguments[2] : "Irresponsible tree" ;
}
accident("Me","Drunk");

Associative Arrays

This method gives all the optional arguments through an associative array. This method is used by a number of JavaScript Frameworks out there. Prototype, Mochikit, Dojo etc. have used this method to enable the programmer to provide more options for any function that is provided by the library. An example...

dojo.io.bind({
	url:        "web2_dot_oh.xml.php",
	mimetype:   "text/xml",
	load:		ajaxHandle
});

Here, the only argument is an associative array that contains all the data needed by the function. One major advantage of the function is that argument order is unnecessary. Each argument have a label to which it is associated - so the programmer will find it easier to remember. Even if they cannot remember it, they will find it the code more readable if they use this method.

This method can be used in the following way...

function person(options) {
	var default_args = {
		'name'	:	"Binny V A",
		'me'	:	true,
		'site'	:	"http://www.bin-co.com/",
		'species':	"Homo Sapien"
	}
	for(var index in default_args) {
		if(typeof options[index] == "undefined") options[index] = default_args[index];
	}
	
	/* options[] has all the data - user provided and optional */
	for(var i in options) {
		alert(i + " = " + options[i]);
	}
}
person({
		'name'	:	"George W. Bush",
		'me'	:	false,
		'site'	:	"miserable failure"
	});

Comments

Ivo Danihelka at 09 Jun, 2007 01:55
It is possible to simplify the

if (!e) e = window.event;

and just write:

e = e || window.event;
Reply to this.
Anonymous at 19 Oct, 2007 10:30
better yet: e ||= window.event;
Reply to this.
Anonymous at 25 Jan, 2008 12:41
BULLSHIT!
Reply to this.
Naruki at 09 Jan, 2009 12:02
I was rather surprised at one early anonymous reply until I went back and read the sample data, which I had skipped in favor of the code. Now I get it: he must be a Bush supporter. He he he. *sigh*

Thanks for the code samples, and the wry commentary.
Reply to this.
Anonymous at 07 Mar, 2008 12:26
Uh, why would you sacrifice readability for ugly syntax and a marginal gain in efficiency?
Reply to this.
Anonymous at 25 Mar, 2008 07:46
it increases overall effeciently if you make MANY of these such calls. thats the whole point of shorthand syntax, if you need readability; add comments, that wont "bog" the script up.
Reply to this.
Jack Ripoff at 23 Jun, 2008 07:30
Because I can... ;)
Reply to this.
DaVince at 31 Jan, 2009 09:02
Readability barely gets compromised if you know of these shorthand coding tricks, and they allow for a bit less typing.

Micro-optimization is kind of meh in these days of modern technology though. :P
Reply to this.
Anonymous at 02 Apr, 2008 01:37
There is not even a marginal efficiency gain. Sorry.
Reply to this.
Anonymous at 04 Apr, 2008 10:59
Theoretically there is. In fact there is, plus for the sake of writing gracefully, save virtual paper and make your statements a bit shorter.

Correction: e ||= window.event throws a syntax error.
In reality you can use
e |= window.event

Example:
x = null;
y = 32;

x |= y
>>>x=32
x |= y
>>>x=32

x = null
y = null
x |= y
>>>x = 0;
Reply to this.
YOzefff at 19 Jun, 2008 08:33
nice one .. I was looking for something like this ... as a PHP programmer I found setting the default vars in the function creation very handy ... I was dissapointed when I found out Javascript didn't have that system ... I use prototype a lot, so I used your associative example and made this one:

function getDefaults(options,default_args)
{
for(var index in default_args)
{
if(typeof options[index] == "undefined") options[index] = default_args[index];
}

return options;
}

so now you can do something like


initialize:function(args)
{
args=getDefaults(args,{debug:false});
}


instance=new Class({debug:true});





Reply to this.
Anonymous at 01 Sep, 2009 03:55
As a PHP programmer I don't care how shitty it looks
Reply to this.
Xurizaemon at 19 Jun, 2008 07:07
Your simple method makes it impossible to pass in a negative optional argument - any of -45, null, or false will get turned into the default in that function.

I remember using something like "typeOf arg == 'undefined'" previously, but right now (testing out FF3) this doesn't work for me.

Hmm ...
Reply to this.
Xurizaemon at 19 Jun, 2008 10:32
oh ... so simple - just a typo by me :) rather that testing if !arg, test if typeof arg == 'undefined'

eg, rather than


function war(enemy,reason) {
if(!enemy) { //The mandatory argument is not present - die with error(no pun intended)
alert("Please choose an enemy before starting a war");
return false;
}
if(!reason) { //If the optional argument is not there, create a new variable with that name.
var reason = "They have Nukes!";
}

/* ...Do what you want with the arguments... */
}


use this:

function war(enemy,reason) {
if( typeof enemy == 'undefined' ) {
alert("Please choose an enemy before starting a war");
return false;
}
if( typeof reason == 'undefined' ) {
var reason = "They have Nukes!";
}

/* ...Do what you want with the arguments... */
}


hope that helps
Reply to this.
Anonymous at 01 Mar, 2010 08:17
Slightly better is:

typeof(arg) === 'undefined'

The triple equals is 'exactly equal in value and type'. It avoids any unintended type coercion.
Reply to this.
Anonymous at 02 Jul, 2008 02:24
x|=y; isn't any more efficient than x=x|y (they are syntactically equivalent) but it is shorter, clearer and more readable. However, x|=y is NOT the same as x=x||y. The former is bitwise or, while the latter is boolean or.
Reply to this.
Anonymous at 13 Nov, 2008 07:21
Quick pedantic correction - There is no such thing as an associative array in javascript. What you're really doing is creating a generic object with a bunch of attributes. The difference is subtle -- an Array is only a generic object with a length() method!

[code]
var foo = new Array();
foo[0] = 'bar';
foo[1] = 'baz';
foo.length;
>>2

var foo new Array();
foo['a'] = 'bar';
foo['b'] = 'baz';
foo.length;
>>0
[/code]
Reply to this.
DaVince at 31 Jan, 2009 09:13
In that case, why does var foo = []; have a length method, too?
Reply to this.
Anonymous at 21 May, 2009 05:29
>>In that case, why does var foo = []; have a length method, too?

Because foo is an Array - "[]" is SHORTHAND for "new Array()", just like "{}" is SHORTHAND for "new Object()".

Do yourself a favor: pickup a copy of "JavaScript: The Good Parts" by Douglas Crockford (O'Reilly, ISBN# 978-0-596-5177-8) and see how real men write code.
Reply to this.
Nobody at 28 May, 2009 05:00
//How if it passed null to the argument?
//Better to check if it is undefined.
function foo(dummy,b,c){
b=(typeof(b)=="undefined")?"This is the default value of b.":b;
c=(typeof(c)=="undefined")?"You haven't passed the argument c!":c;
alert("dummy: "+dummy+"\nb: "+b+"\nc: "+c);
}
foo(); //Will alert:
/*
dummy: undefined
b: This is the default value of b.
c: You haven't passed the argument c!
*/
Reply to this.
Skews Me at 09 Jun, 2009 01:00
So now that we have the functionality for storing indexed items in RAM, the next step would be long term data storage. For example, a gaming calculator I wrote uses a cookie to store player stats between sessions. Methods to catalog the items be they tokens or actual software is crucial now in the evolution of computer programming.

Functions like toData(), toText(), toHTML(), toJavaScript(), toCSharp(), etc., in addition to stock toString() calls should be common.

Ever call toString() on a javascript function? Done properly it will show you the function's source code. Everything should have something like that built in. Open Source FTW (for the win)!
Reply to this.
Skews Me at 13 Jul, 2009 02:27
I just blogged about many of the steps I needed to take to create a dynamic table builder which includes examples of your code.

http://skewsme.com/observations4.html#tables
Reply to this.
L. Simon at 08 Sep, 2009 08:28
There is no such thing as an "associative array" in Javascript. You've created a generic object with several properties.

The kicker to that is that the .length property of your object will not reflect the number of properties you've assigned - so you can't step through them with a for loop.
Reply to this.
Anonymous at 12 Sep, 2009 07:12
Just saying thanks for all the great comments on this page ;-)
Reply to this.
Comment

Please dont enter you comments in this form - this is a fake form to confuse spamming bots. The next form is the real one.




Comment




Comment Formating : HTML tags a, strong, em, b, i, code, pre, p and br allowed. Other tags will be shown as code(< will become &lt;). Urls, Line breaks will be auto-formated.