In javascript, there is only one function with any given name and if multiple functions with the same name are declared, the last one declared will be the one that is active.
You can however test the arguments that are passed to your function and implement many of the same types of behaviors that function overloading is designed to handle. In fact, in some cases you can do even more.
In your specific example:
function abc(s, t) {
// test to see if the t argument was passed
if (t !== undefined) {
console.log('was called as abc(s,t)');
} else {
console.log('was called as abc(s)');
}
}
abc('1'); // outputs 'was called as abc(s)'
abc('1', '2'); // outputs 'was called as abc(s,t)'
But, you can also get much, much more creative (and useful).
For example, the jQuery .css()
method can be called five different ways.
.css( propertyName )
.css( propertyNames )
.css( propertyName, value )
.css( propertyName, function(index, value) )
.css( properties )
The code inside the .css()
method examines the type and number of the arguments to figure out which way it is being called and therefore exactly what operation to carry out.
Let's look at how this could be done to figure out which of the 5 forms of this function are being used:
css: function(prop, value) {
// first figure out if we only have one argument
if (value === undefined) {
if (typeof prop === "string") {
// we have a simple request for a single css property by string name
// of this form: .css( propertyName )
} else if (Array.isArray(prop)) {
// we have a request for an array of properties
// of this form: .css( propertyNames )
} else if (typeof prop === "object") {
// property-value pairs of css to set
// of this form: .css( properties )
}
} else {
if (typeof value === "function") {
// of this form: .css( propertyName, function(index, value) )
} else {
// of this form: .css( propertyName, value )
}
}
}
You can also implement optional arguments. For example, jQuery's .hide()
can accept many forms. One of the forms is .hide( [duration ] [, complete ] )
where both the duration and the completion function are optional. You can pass nothing, just a duration or both a duration and completion callback function. That could be implemented like this:
hide: function(duration, fn) {
// default the duration to zero if not present
duration = duration || 0;
// default the completion function to a dummy function if not present
fn = fn || function() {};
// now the code can proceed knowing that there are valid arguments for both
// duration and fn whether they were originally passed or not
}
I find one of the most useful ways of using these variable arguments are to allow code to support a variety of different argument types so that no matter what state your arguments are in, you can just pass them as you have them without having to convert them to some universal type. For example, in this implementation of a set object in javascript, the .add()
method can take all of these different forms of arguments:
s.add(key)
s.add(key1, key2, key3)
s.add([key1, key2, key3])
s.add(key1, [key8, key9], key2, [key4, key5])
s.add(otherSet) // any other set object
s.add(arrayLikeObject) // such as an HTMLCollection or nodeList
This both accepts a variable number of arguments and it accepts a number of different types for each argument and it will adapt based on what is passed to it. So, you can initialize a set via a list of keys, an array of keys, from another set, from a pseudo array or any mixture of those types. Internally, the code just iterates through each argument that was passed to the function, checks the type of the argument and acts accordingly.
You can see the code here on GitHub for further info on how this is done.