[javascript] Function overloading in Javascript - Best practices

What is the best way(s) to fake function overloading in Javascript?

I know it is not possible to overload functions in Javascript as in other languages. If I needed a function with two uses foo(x) and foo(x,y,z) which is the best / preferred way:

  1. Using different names in the first place
  2. Using optional arguments like y = y || 'default'
  3. Using number of arguments
  4. Checking types of arguments
  5. Or how?

This question is related to javascript overloading

The answer is


This is an old question but one that I think needs another entry (although I doubt anyone will read it). The use of Immediately Invoked Function Expressions (IIFE) can be used in conjunction with closures and inline functions to allow for function overloading. Consider the following (contrived) example:

var foo;

// original 'foo' definition
foo = function(a) {
  console.log("a: " + a);
}

// define 'foo' to accept two arguments
foo = (function() {
  // store a reference to the previous definition of 'foo'
  var old = foo;

  // use inline function so that you can refer to it internally
  return function newFoo(a,b) {

    // check that the arguments.length == the number of arguments 
    // defined for 'newFoo'
    if (arguments.length == newFoo.length) {
      console.log("a: " + a);
      console.log("b: " + b);

    // else if 'old' is a function, apply it to the arguments
    } else if (({}).toString.call(old) === '[object Function]') {
      old.apply(null, arguments);
    }
  }
})();

foo(1);
> a: 1
foo(1,2);
> a: 1
> b: 2
foo(1,2,3)
> a: 1

In short, the use of the IIFE creates a local scope, allowing us to define the private variable old to store a reference to the initial definition of the function foo. This function then returns an inline function newFoo that logs the contents of both two arguments if it is passed exactly two arguments a and b or calls the old function if arguments.length !== 2. This pattern can be repeated any number of times to endow one variable with several different functional defitions.


I just tried this, maybe it suits your needs. Depending on the number of the arguments, you can access a different function. You initialize it the first time you call it. And the function map is hidden in the closure.

TEST = {};

TEST.multiFn = function(){
    // function map for our overloads
    var fnMap = {};

    fnMap[0] = function(){
        console.log("nothing here");
        return this;    //    support chaining
    }

    fnMap[1] = function(arg1){
        //    CODE here...
        console.log("1 arg: "+arg1);
        return this;
    };

    fnMap[2] = function(arg1, arg2){
        //    CODE here...
        console.log("2 args: "+arg1+", "+arg2);
        return this;
    };

    fnMap[3] = function(arg1,arg2,arg3){
        //    CODE here...
        console.log("3 args: "+arg1+", "+arg2+", "+arg3);
        return this;
    };

    console.log("multiFn is now initialized");

    //    redefine the function using the fnMap in the closure
    this.multiFn = function(){
        fnMap[arguments.length].apply(this, arguments);
        return this;
    };

    //    call the function since this code will only run once
    this.multiFn.apply(this, arguments);

    return this;    
};

Test it.

TEST.multiFn("0")
    .multiFn()
    .multiFn("0","1","2");

As of July 2017, the following has been the common technique. Note that we can also perform type checking within the function.

function f(...rest){   // rest is an array
   console.log(rest.length);
   for (v of rest) if (typeof(v)=="number")console.log(v);
}
f(1,2,3);  // 3 1 2 3

If I needed a function with two uses foo(x) and foo(x,y,z) which is the best / preferred way?

The issue is that JavaScript does NOT natively support method overloading. So, if it sees/parses two or more functions with a same names it’ll just consider the last defined function and overwrite the previous ones.

One of the way I think is suitable for most of the case is follows -

Lets say you have method

function foo(x)
{
} 

Instead of overloading method which is not possible in javascript you can define a new method

fooNew(x,y,z)
{
}

and then modify the 1st function as follows -

function foo(arguments)
{
  if(arguments.length==2)
  {
     return fooNew(arguments[0],  arguments[1]);
  }
} 

If you have many such overloaded methods consider using switch than just if-else statements.


I would like to share a useful example of overloaded-like approach.

function Clear(control)
{
  var o = typeof control !== "undefined" ? control : document.body;
  var children = o.childNodes;
  while (o.childNodes.length > 0)
    o.removeChild(o.firstChild);
}

Usage: Clear(); // Clears all the document

Clear(myDiv); // Clears panel referenced by myDiv


There is no real function overloading in JavaScript since it allows to pass any number of parameters of any type. You have to check inside the function how many arguments have been passed and what type they are.


While Default parameters is not overloading, it might solve some of the issues that developers face in this area. The input is strictly decided by the order, you can not re-order as you wish as in classical overloading:

function transformer(
    firstNumber = 1,
    secondNumber = new Date().getFullYear(),
    transform = function multiply(firstNumber, secondNumber) {
        return firstNumber * secondNumber;
    }
) {
    return transform(firstNumber, secondNumber);
}

console.info(transformer());
console.info(transformer(8));
console.info(transformer(2, 6));
console.info(transformer(undefined, 65));

function add(firstNumber, secondNumber) {
    return firstNumber + secondNumber;
}
console.info(transformer(undefined, undefined, add));
console.info(transformer(3, undefined, add));

Results in (for year 2020):

2020
16160
12
65
2021
2023

More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters


Another way to approach this is by using the special variable: arguments, this is an implementation:

function sum() {
    var x = 0;
    for (var i = 0; i < arguments.length; ++i) {
        x += arguments[i];
    }
    return x;
}

so you can modify this code to:

function sum(){
    var s = 0;
    if (typeof arguments[0] !== "undefined") s += arguments[0];
.
.
.
    return s;
}

The first option really deserves attention cause it's the thing I've come up in quite complex code setup. So, my answer is

  1. Using different names in the first place

With a little but essential hint, names should look different for computer, but not for you. Name overloaded functions like: func, func1, func2.


Function Overloading via Dynamic Polymorphism in 100 lines of JS

This is from a larger body of code which includes the isFn, isArr, etc. type checking functions. The VanillaJS version below has been reworked to remove all external dependencies, however you will have to define you're own type checking functions for use in the .add() calls.

Note: This is a self-executing function (so we can have a closure/closed scope), hence the assignment to window.overload rather than function overload() {...}.

window.overload = function () {
    "use strict"

    var a_fnOverloads = [],
        _Object_prototype_toString = Object.prototype.toString
    ;

    function isFn(f) {
        return (_Object_prototype_toString.call(f) === '[object Function]');
    } //# isFn

    function isObj(o) {
        return !!(o && o === Object(o));
    } //# isObj

    function isArr(a) {
        return (_Object_prototype_toString.call(a) === '[object Array]');
    } //# isArr

    function mkArr(a) {
        return Array.prototype.slice.call(a);
    } //# mkArr

    function fnCall(fn, vContext, vArguments) {
        //# <ES5 Support for array-like objects
        //#     See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Browser_compatibility
        vArguments = (isArr(vArguments) ? vArguments : mkArr(vArguments));

        if (isFn(fn)) {
            return fn.apply(vContext || this, vArguments);
        }
    } //# fnCall

    //# 
    function registerAlias(fnOverload, fn, sAlias) {
        //# 
        if (sAlias && !fnOverload[sAlias]) {
            fnOverload[sAlias] = fn;
        }
    } //# registerAlias

    //# 
    function overload(vOptions) {
        var oData = (isFn(vOptions) ?
                { default: vOptions } :
                (isObj(vOptions) ?
                    vOptions :
                    {
                        default: function (/*arguments*/) {
                            throw "Overload not found for arguments: [" + mkArr(arguments) + "]";
                        }
                    }
                )
            ),
            fnOverload = function (/*arguments*/) {
                var oEntry, i, j,
                    a = arguments,
                    oArgumentTests = oData[a.length] || []
                ;

                //# Traverse the oArgumentTests for the number of passed a(rguments), defaulting the oEntry at the beginning of each loop
                for (i = 0; i < oArgumentTests.length; i++) {
                    oEntry = oArgumentTests[i];

                    //# Traverse the passed a(rguments), if a .test for the current oArgumentTests fails, reset oEntry and fall from the a(rgument)s loop
                    for (j = 0; j < a.length; j++) {
                        if (!oArgumentTests[i].tests[j](a[j])) {
                            oEntry = undefined;
                            break;
                        }
                    }

                    //# If all of the a(rgument)s passed the .tests we found our oEntry, so break from the oArgumentTests loop
                    if (oEntry) {
                        break;
                    }
                }

                //# If we found our oEntry above, .fn.call its .fn
                if (oEntry) {
                    oEntry.calls++;
                    return fnCall(oEntry.fn, this, a);
                }
                //# Else we were unable to find a matching oArgumentTests oEntry, so .fn.call our .default
                else {
                    return fnCall(oData.default, this, a);
                }
            } //# fnOverload
        ;

        //# 
        fnOverload.add = function (fn, a_vArgumentTests, sAlias) {
            var i,
                bValid = isFn(fn),
                iLen = (isArr(a_vArgumentTests) ? a_vArgumentTests.length : 0)
            ;

            //# 
            if (bValid) {
                //# Traverse the a_vArgumentTests, processinge each to ensure they are functions (or references to )
                for (i = 0; i < iLen; i++) {
                    if (!isFn(a_vArgumentTests[i])) {
                        bValid = _false;
                    }
                }
            }

            //# If the a_vArgumentTests are bValid, set the info into oData under the a_vArgumentTests's iLen
            if (bValid) {
                oData[iLen] = oData[iLen] || [];
                oData[iLen].push({
                    fn: fn,
                    tests: a_vArgumentTests,
                    calls: 0
                });

                //# 
                registerAlias(fnOverload, fn, sAlias);

                return fnOverload;
            }
            //# Else one of the passed arguments was not bValid, so throw the error
            else {
                throw "poly.overload: All tests must be functions or strings referencing `is.*`.";
            }
        }; //# overload*.add

        //# 
        fnOverload.list = function (iArgumentCount) {
            return (arguments.length > 0 ? oData[iArgumentCount] || [] : oData);
        }; //# overload*.list

        //# 
        a_fnOverloads.push(fnOverload);
        registerAlias(fnOverload, oData.default, "default");

        return fnOverload;
    } //# overload

    //# 
    overload.is = function (fnTarget) {
        return (a_fnOverloads.indexOf(fnTarget) > -1);
    } //# overload.is

    return overload;
}();

Usage:

The caller defines their overloaded functions by assigning a variable to the return of overload(). Thanks to chaining, the additional overloads can be defined in series:

var myOverloadedFn = overload(function(){ console.log("default", arguments) })
    .add(function(){ console.log("noArgs", arguments) }, [], "noArgs")
    .add(function(){ console.log("str", arguments) }, [function(s){ return typeof s === 'string' }], "str")
;

The single optional argument to overload() defines the "default" function to call if the signature cannot be identified. The arguments to .add() are:

  1. fn: function defining the overload;
  2. a_vArgumentTests: Array of functions defining the tests to run on the arguments. Each function accepts a single argument and returns truethy based on if the argument is valid;
  3. sAlias (Optional): string defining the alias to directly access the overload function (fn), e.g. myOverloadedFn.noArgs() will call that function directly, avoiding the dynamic polymorphism tests of the arguments.

This implementation actually allows for more than just traditional function overloads as the second a_vArgumentTests argument to .add() in practice defines custom types. So, you could gate arguments not only based on type, but on ranges, values or collections of values!

If you look through the 145 lines of code for overload() you'll see that each signature is categorized by the number of arguments passed to it. This is done so that we're limiting the number of tests we are running. I also keep track of a call count. With some additional code, the arrays of overloaded functions could be re-sorted so that more commonly called functions are tested first, again adding some measure of performance enhancement.

Now, there are some caveats... As Javascript is loosely typed, you will have to be careful with your vArgumentTests as an integer could be validated as a float, etc.

JSCompress.com version (1114 bytes, 744 bytes g-zipped):

window.overload=function(){'use strict';function b(n){return'[object Function]'===m.call(n)}function c(n){return!!(n&&n===Object(n))}function d(n){return'[object Array]'===m.call(n)}function e(n){return Array.prototype.slice.call(n)}function g(n,p,q){if(q=d(q)?q:e(q),b(n))return n.apply(p||this,q)}function h(n,p,q){q&&!n[q]&&(n[q]=p)}function k(n){var p=b(n)?{default:n}:c(n)?n:{default:function(){throw'Overload not found for arguments: ['+e(arguments)+']'}},q=function(){var r,s,t,u=arguments,v=p[u.length]||[];for(s=0;s<v.length;s++){for(r=v[s],t=0;t<u.length;t++)if(!v[s].tests[t](u[t])){r=void 0;break}if(r)break}return r?(r.calls++,g(r.fn,this,u)):g(p.default,this,u)};return q.add=function(r,s,t){var u,v=b(r),w=d(s)?s.length:0;if(v)for(u=0;u<w;u++)b(s[u])||(v=_false);if(v)return p[w]=p[w]||[],p[w].push({fn:r,tests:s,calls:0}),h(q,r,t),q;throw'poly.overload: All tests must be functions or strings referencing `is.*`.'},q.list=function(r){return 0<arguments.length?p[r]||[]:p},l.push(q),h(q,p.default,'default'),q}var l=[],m=Object.prototype.toString;return k.is=function(n){return-1<l.indexOf(n)},k}();

check this out. It is very cool. http://ejohn.org/blog/javascript-method-overloading/ Trick Javascript to allow you to do calls like this:

var users = new Users();
users.find(); // Finds all
users.find("John"); // Finds users by name
users.find("John", "Resig"); // Finds users by first and last name

We made over.js to solve this problem is a very elegant way. You can do:

var obj = {

  /**
   * Says something in the console.
   *
   * say(msg) - Says something once.
   * say(msg, times) - Says something many times.
   */
  say: Over(
    function(msg$string){
      console.info(msg$string);
    },
    function(msg$string, times$number){
      for (var i = 0; i < times$number; i++) this.say(msg$string);
    }
  )

};

I'm not sure about best practice, but here is how I do it:

/*
 * Object Constructor
 */
var foo = function(x) {
    this.x = x;
};

/*
 * Object Protoype
 */
foo.prototype = {
    /*
     * f is the name that is going to be used to call the various overloaded versions
     */
    f: function() {

        /*
         * Save 'this' in order to use it inside the overloaded functions
         * because there 'this' has a different meaning.
         */   
        var that = this;  

        /* 
         * Define three overloaded functions
         */
        var f1 = function(arg1) {
            console.log("f1 called with " + arg1);
            return arg1 + that.x;
        }

        var f2 = function(arg1, arg2) {
             console.log("f2 called with " + arg1 + " and " + arg2);
             return arg1 + arg2 + that.x;
        }

        var f3 = function(arg1) {
             console.log("f3 called with [" + arg1[0] + ", " + arg1[1] + "]");
             return arg1[0] + arg1[1];
        }

        /*
         * Use the arguments array-like object to decide which function to execute when calling f(...)
         */
        if (arguments.length === 1 && !Array.isArray(arguments[0])) {
            return f1(arguments[0]);
        } else if (arguments.length === 2) {
            return f2(arguments[0], arguments[1]);
        } else if (arguments.length === 1 && Array.isArray(arguments[0])) {
            return f3(arguments[0]);
        }
    } 
}

/* 
 * Instantiate an object
 */
var obj = new foo("z");

/*
 * Call the overloaded functions using f(...)
 */
console.log(obj.f("x"));         // executes f1, returns "xz"
console.log(obj.f("x", "y"));    // executes f2, returns "xyz"
console.log(obj.f(["x", "y"]));  // executes f3, returns "xy"

I often do this:

C#:

public string CatStrings(string p1)                  {return p1;}
public string CatStrings(string p1, int p2)          {return p1+p2.ToString();}
public string CatStrings(string p1, int p2, bool p3) {return p1+p2.ToString()+p3.ToString();}

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

JavaScript Equivalent:

function CatStrings(p1, p2, p3)
{
  var s = p1;
  if(typeof p2 !== "undefined") {s += p2;}
  if(typeof p3 !== "undefined") {s += p3;}
  return s;
};

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

This particular example is actually more elegant in javascript than C#. Parameters which are not specified are 'undefined' in javascript, which evaluates to false in an if statement. However, the function definition does not convey the information that p2 and p3 are optional. If you need a lot of overloading, jQuery has decided to use an object as the parameter, for example, jQuery.ajax(options). I agree with them that this is the most powerful and clearly documentable approach to overloading, but I rarely need more than one or two quick optional parameters.

EDIT: changed IF test per Ian's suggestion


The best way really depends on the function and the arguments. Each of your options is a good idea in different situations. I generally try these in the following order until one of them works:

  1. Using optional arguments like y = y || 'default'. This is convenient if you can do it, but it may not always work practically, e.g. when 0/null/undefined would be a valid argument.

  2. Using number of arguments. Similar to the last option but may work when #1 doesn't work.

  3. Checking types of arguments. This can work in some cases where the number of arguments is the same. If you can't reliably determine the types, you may need to use different names.

  4. Using different names in the first place. You may need to do this if the other options won't work, aren't practical, or for consistency with other related functions.


There is no way to function overloading in javascript. So, I recommend like the following by typeof() method instead of multiple function to fake overloading.

function multiTypeFunc(param)
{
    if(typeof param == 'string') {
        alert("I got a string type parameter!!");
     }else if(typeof param == 'number') {
        alert("I got a number type parameter!!");
     }else if(typeof param == 'boolean') {
        alert("I got a boolean type parameter!!");
     }else if(typeof param == 'object') {
        alert("I got a object type parameter!!");
     }else{
        alert("error : the parameter is undefined or null!!");
     }
}

Good luck!


There is no real function overloading in JavaScript since it allows to pass any number of parameters of any type. You have to check inside the function how many arguments have been passed and what type they are.


There are two ways you could approach this better:

  1. Pass a dictionary (associative array) if you want to leave a lot of flexibility

  2. Take an object as the argument and use prototype based inheritance to add flexibility.


The best way really depends on the function and the arguments. Each of your options is a good idea in different situations. I generally try these in the following order until one of them works:

  1. Using optional arguments like y = y || 'default'. This is convenient if you can do it, but it may not always work practically, e.g. when 0/null/undefined would be a valid argument.

  2. Using number of arguments. Similar to the last option but may work when #1 doesn't work.

  3. Checking types of arguments. This can work in some cases where the number of arguments is the same. If you can't reliably determine the types, you may need to use different names.

  4. Using different names in the first place. You may need to do this if the other options won't work, aren't practical, or for consistency with other related functions.


While Default parameters is not overloading, it might solve some of the issues that developers face in this area. The input is strictly decided by the order, you can not re-order as you wish as in classical overloading:

function transformer(
    firstNumber = 1,
    secondNumber = new Date().getFullYear(),
    transform = function multiply(firstNumber, secondNumber) {
        return firstNumber * secondNumber;
    }
) {
    return transform(firstNumber, secondNumber);
}

console.info(transformer());
console.info(transformer(8));
console.info(transformer(2, 6));
console.info(transformer(undefined, 65));

function add(firstNumber, secondNumber) {
    return firstNumber + secondNumber;
}
console.info(transformer(undefined, undefined, add));
console.info(transformer(3, undefined, add));

Results in (for year 2020):

2020
16160
12
65
2021
2023

More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters


As this post already contains a lot of different solutions i thought i post another one.

function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

function overload() {
   var functions = arguments;
   var nroffunctionsarguments = [arguments.length];
    for (var i = 0; i < arguments.length; i++) {
        nroffunctionsarguments[i] = arguments[i].length;
    }
    var unique = nroffunctionsarguments.filter(onlyUnique);
    if (unique.length === arguments.length) {
        return function () {
            var indexoffunction = nroffunctionsarguments.indexOf(arguments.length);
            return functions[indexoffunction].apply(this, arguments);
        }
    }
    else throw new TypeError("There are multiple functions with the same number of parameters");

}

this can be used as shown below:

var createVector = overload(
        function (length) {
            return { x: length / 1.414, y: length / 1.414 };
        },
        function (a, b) {
            return { x: a, y: b };
        },
        function (a, b,c) {
            return { x: a, y: b, z:c};
        }
    );
console.log(createVector(3, 4));
console.log(createVector(3, 4,5));
console.log(createVector(7.07));

This solution is not perfect but i only want to demonstrate how it could be done.


Since JavaScript doesn't have function overload options object can be used instead. If there are one or two required arguments, it's better to keep them separate from the options object. Here is an example on how to use options object and populated values to default value in case if value was not passed in options object.

    function optionsObjectTest(x, y, opts) {
        opts = opts || {}; // default to an empty options object

        var stringValue = opts.stringValue || "string default value";
        var boolValue = !!opts.boolValue; // coerces value to boolean with a double negation pattern
        var numericValue = opts.numericValue === undefined ? 123 : opts.numericValue;

        return "{x:" + x + ", y:" + y + ", stringValue:'" + stringValue + "', boolValue:" + boolValue + ", numericValue:" + numericValue + "}";

}

here is an example on how to use options object


I've been using this function to prettify my overloads for years:

function overload(){
  const fs = arguments, fallback = fs[fs.length - 1];
  return function(){
    const f = fs[arguments.length] || (arguments.length >= fs.length ? fallback : null);
    return f.apply(this, arguments);
  }
}

Demostrated:

function curry1(f){
  return curry2(f, f.length);
}

function curry2(f, minimum){
  return function(...applied){
    if (applied.length >= minimum) {
      return f.apply(this, applied);
    } else {
      return curry2(function(...args){
        return f.apply(this, applied.concat(args));
      }, minimum - applied.length);
    }
  }
}

export const curry = overload(null, curry1, curry2);

Take a look at jQuery's off method:

  function off( types, selector, fn ) {
    var handleObj, type;
    if ( types && types.preventDefault && types.handleObj ) {

        // ( event )  dispatched jQuery.Event
        handleObj = types.handleObj;
        jQuery( types.delegateTarget ).off(
            handleObj.namespace ?
                handleObj.origType + "." + handleObj.namespace :
                handleObj.origType,
            handleObj.selector,
            handleObj.handler
        );
        return this;
    }
    if ( typeof types === "object" ) {

        // ( types-object [, selector] )
        for ( type in types ) {
            this.off( type, selector, types[ type ] );
        }
        return this;
    }
    if ( selector === false || typeof selector === "function" ) {

        // ( types [, fn] )
        fn = selector;
        selector = undefined;
    }
    if ( fn === false ) {
        fn = returnFalse;
    }
    return this.each( function() {
        jQuery.event.remove( this, types, fn, selector );
    } );
  }

Many overloaded functions when optimized for performance are nigh unreadable. You have to decipher the head of the function. This is perhaps faster than using an overload function like I provide; however, it is slower from a human perspective with regard to identifying which overload was called.


Something like this can be done for function overloading.

function addCSS(el, prop, val) {
  return {
    2: function() {
      // when two arguments are set
      // now prop is an oject
      for (var i in prop) {
          el.style[i] = prop[i];
      }
    },
    3: function() {
      // when three arguments are set
      el.style[prop] = val;
    }
    }[arguments.length]();
}
// usage
var el = document.getElementById("demo");
addCSS(el, "color", "blue");
addCSS(el, {
    "backgroundColor": "black",
  "padding": "10px"
});

Source


there is no actual overloading in JS, anyway we still can simulate method overloading in several ways:

method #1: use object

function test(x,options){
  if("a" in options)doSomething();
  else if("b" in options)doSomethingElse();
}
test("ok",{a:1});
test("ok",{b:"string"});

method #2: use rest (spread) parameters

function test(x,...p){
 if(p[2])console.log("3 params passed"); //or if(typeof p[2]=="string")
else if (p[1])console.log("2 params passed");
else console.log("1 param passed");
}

method #3: use undefined

function test(x, y, z){
 if(typeof(z)=="undefined")doSomething();
}

method #4: type checking

function test(x){
 if(typeof(x)=="string")console.log("a string passed")
 else ...
}

There are two ways you could approach this better:

  1. Pass a dictionary (associative array) if you want to leave a lot of flexibility

  2. Take an object as the argument and use prototype based inheritance to add flexibility.


So I really liked this way of doing things that I found in secrets of the javascript ninja

function addMethod(object,name,fn){
  var old = object[name];
  object[name] = function(){
    if (fn.length == arguments.length){
      return fn.apply(this,arguments);
    } else if(typeof old == 'function'){
        return old.apply(this,arguments);
    }
  }
}

you then use addMethod to add overloaded functions to any object. The main confusion in this code for me was the use of fn.length == arguments.length -- this works because fn.length is the number of expected parameters, while arguments.length is the number of parameters that are actually called with the function. The reason the anonymous function has no argument is because you can pass in any number of arguments in javascript and the language is forgiving.

I liked this because you can use it everywhere - just create this function and simply use the method in whatever code base you want.

It also avoids having a ridiculously large if/switch statement, which becomes hard to read if you start writing complex code (the accepted answer will result in this).

In terms of cons, I guess the code is initially a little obscure...but I'm not sure of others?


#Forwarding Pattern => the best practice on JS overloading Forward to another function which name is built from the 3rd & 4th points :

  1. Using number of arguments
  2. Checking types of arguments
window['foo_'+arguments.length+'_'+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments)

#Application on your case :

 function foo(...args){
          return window['foo_' + args.length+'_'+Array.from(args).map((arg)=>typeof arg).join('_')](...args);

  }
   //------Assuming that `x` , `y` and `z` are String when calling `foo` . 
  
  /**-- for :  foo(x)*/
  function foo_1_string(){
  }
  /**-- for : foo(x,y,z) ---*/
  function foo_3_string_string_string(){
      
  }

#Other Complex Sample :

      function foo(...args){
          return window['foo_'+args.length+'_'+Array.from(args).map((arg)=>typeof arg).join('_')](...args);
       }

        /** one argument & this argument is string */
      function foo_1_string(){

      }
       //------------
       /** one argument & this argument is object */
      function foo_1_object(){

      }
      //----------
      /** two arguments & those arguments are both string */
      function foo_2_string_string(){

      }
       //--------
      /** Three arguments & those arguments are : id(number),name(string), callback(function) */
      function foo_3_number_string_function(){
                let args=arguments;
                  new Person(args[0],args[1]).onReady(args[3]);
      }
     
       //--- And so on ....   

You can use this methode

function func1(a, b, c) {
  console.log(arguments[0]);
  // expected output: 1

  console.log(arguments[1]);
  // expected output: 2

  console.log(arguments[2]);
  // expected output: 3
}

func1(1, 2, 3);

ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments


The best way really depends on the function and the arguments. Each of your options is a good idea in different situations. I generally try these in the following order until one of them works:

  1. Using optional arguments like y = y || 'default'. This is convenient if you can do it, but it may not always work practically, e.g. when 0/null/undefined would be a valid argument.

  2. Using number of arguments. Similar to the last option but may work when #1 doesn't work.

  3. Checking types of arguments. This can work in some cases where the number of arguments is the same. If you can't reliably determine the types, you may need to use different names.

  4. Using different names in the first place. You may need to do this if the other options won't work, aren't practical, or for consistency with other related functions.


I would like to share a useful example of overloaded-like approach.

function Clear(control)
{
  var o = typeof control !== "undefined" ? control : document.body;
  var children = o.childNodes;
  while (o.childNodes.length > 0)
    o.removeChild(o.firstChild);
}

Usage: Clear(); // Clears all the document

Clear(myDiv); // Clears panel referenced by myDiv


I like @AntouanK's approach. I often find myself offering a function with different numbers o parameters and different types. Sometimes they don't follow a order. I use to map looking the types of parameters:

findUDPServers: function(socketProperties, success, error) {
    var fqnMap = [];

    fqnMap['undefined'] = fqnMap['function'] = function(success, error) {
        var socketProperties = {name:'HELLO_SERVER'};

        this.searchServers(socketProperties, success, error);
    };

    fqnMap['object'] = function(socketProperties, success, error) {
        var _socketProperties = _.merge({name:'HELLO_SERVER'}, socketProperties || {});

        this.searchServers(_socketProperties, success, error);
    };

    fqnMap[typeof arguments[0]].apply(this, arguments);
}

I've been using this function to prettify my overloads for years:

function overload(){
  const fs = arguments, fallback = fs[fs.length - 1];
  return function(){
    const f = fs[arguments.length] || (arguments.length >= fs.length ? fallback : null);
    return f.apply(this, arguments);
  }
}

Demostrated:

function curry1(f){
  return curry2(f, f.length);
}

function curry2(f, minimum){
  return function(...applied){
    if (applied.length >= minimum) {
      return f.apply(this, applied);
    } else {
      return curry2(function(...args){
        return f.apply(this, applied.concat(args));
      }, minimum - applied.length);
    }
  }
}

export const curry = overload(null, curry1, curry2);

Take a look at jQuery's off method:

  function off( types, selector, fn ) {
    var handleObj, type;
    if ( types && types.preventDefault && types.handleObj ) {

        // ( event )  dispatched jQuery.Event
        handleObj = types.handleObj;
        jQuery( types.delegateTarget ).off(
            handleObj.namespace ?
                handleObj.origType + "." + handleObj.namespace :
                handleObj.origType,
            handleObj.selector,
            handleObj.handler
        );
        return this;
    }
    if ( typeof types === "object" ) {

        // ( types-object [, selector] )
        for ( type in types ) {
            this.off( type, selector, types[ type ] );
        }
        return this;
    }
    if ( selector === false || typeof selector === "function" ) {

        // ( types [, fn] )
        fn = selector;
        selector = undefined;
    }
    if ( fn === false ) {
        fn = returnFalse;
    }
    return this.each( function() {
        jQuery.event.remove( this, types, fn, selector );
    } );
  }

Many overloaded functions when optimized for performance are nigh unreadable. You have to decipher the head of the function. This is perhaps faster than using an overload function like I provide; however, it is slower from a human perspective with regard to identifying which overload was called.


Here is an approach that allows real method overloading using parameter types, shown below:

Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);

Edit (2018): Since this was written in 2011, the speed of direct method calls has greatly increased while the speed of overloaded methods have not.

It is not an approach I would recommend, but it is a worthwhile thought exercise to think about how you can solve these types of problems.


Here is a benchmark of the different approaches - https://jsperf.com/function-overloading. It shows that function overloading (taking types into account) can be around 13 times slower in Google Chrome's V8 as of 16.0(beta).

As well as passing an object (i.e. {x: 0, y: 0}), one can also take the C approach when appropriate, naming the methods accordingly. For example, Vector.AddVector(vector), Vector.AddIntegers(x, y, z, ...) and Vector.AddArray(integerArray). You can look at C libraries, such as OpenGL for naming inspiration.

Edit: I've added a benchmark for passing an object and testing for the object using both 'param' in arg and arg.hasOwnProperty('param'), and function overloading is much faster than passing an object and checking for properties (in this benchmark at least).

From a design perspective, function overloading is only valid or logical if the overloaded parameters correspond to the same action. So it stands to reason that there ought to be an underlying method that is only concerned with specific details, otherwise that may indicate inappropriate design choices. So one could also resolve the use of function overloading by converting data to a respective object. Of course one must consider the scope of the problem as there's no need in making elaborate designs if your intention is just to print a name, but for the design of frameworks and libraries such thought is justified.

My example comes from a Rectangle implementation - hence the mention of Dimension and Point. Perhaps Rectangle could add a GetRectangle() method to the Dimension and Point prototype, and then the function overloading issue is sorted. And what about primitives? Well, we have argument length, which is now a valid test since objects have a GetRectangle() method.

function Dimension() {}
function Point() {}

var Util = {};

Util.Redirect = function (args, func) {
  'use strict';
  var REDIRECT_ARGUMENT_COUNT = 2;

  if(arguments.length - REDIRECT_ARGUMENT_COUNT !== args.length) {
    return null;
  }

  for(var i = REDIRECT_ARGUMENT_COUNT; i < arguments.length; ++i) {
    var argsIndex = i-REDIRECT_ARGUMENT_COUNT;
    var currentArgument = args[argsIndex];
    var currentType = arguments[i];
    if(typeof(currentType) === 'object') {
      currentType = currentType.constructor;
    }
    if(typeof(currentType) === 'number') {
      currentType = 'number';
    }
    if(typeof(currentType) === 'string' && currentType === '') {
      currentType = 'string';
    }
    if(typeof(currentType) === 'function') {
      if(!(currentArgument instanceof currentType)) {
        return null;
      }
    } else {
      if(typeof(currentArgument) !== currentType) {
        return null;
      }
    } 
  }
  return [func.apply(this, args)];
}

function FuncPoint(point) {}
function FuncDimension(dimension) {}
function FuncDimensionPoint(dimension, point) {}
function FuncXYWidthHeight(x, y, width, height) { }

function Func() {
  Util.Redirect(arguments, FuncPoint, Point);
  Util.Redirect(arguments, FuncDimension, Dimension);
  Util.Redirect(arguments, FuncDimensionPoint, Dimension, Point);
  Util.Redirect(arguments, FuncXYWidthHeight, 0, 0, 0, 0);
}

Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);

Function overloading in Javascript:

Function overloading is the ability of a programming language to create multiple functions of the same name with different implementations. when an overloaded function is called it will run function a specific implementation of that function appropriate to the context of the call. This context is usually the amount of arguments is receives, and it allows one function call to behave differently depending on context.

Javascript doesn't have built-in function overloading. However, this behaviour can be emulated in many ways. Here is a convenient simple one:

_x000D_
_x000D_
function sayHi(a, b) {_x000D_
  console.log('hi there ' + a);_x000D_
  if (b) { console.log('and ' + b) } // if the parameter is present, execute the block_x000D_
}_x000D_
_x000D_
sayHi('Frank', 'Willem');
_x000D_
_x000D_
_x000D_

In scenarios where you don't know how many arguments you will be getting you can use the rest operator which is three dots .... It will convert the remainder of the arguments into an array. Beware of browser compatibilty though. Here is an example:

_x000D_
_x000D_
function foo (a, ...b) {_x000D_
  console.log(b);_x000D_
}_x000D_
_x000D_
foo(1,2,3,4);_x000D_
foo(1,2);
_x000D_
_x000D_
_x000D_


You can now do function overloading in ECMAScript 2018 without polyfills, checking var length/type, etc., just use the spread syntax.

_x000D_
_x000D_
function foo(var1, var2, opts){_x000D_
  // set default values for parameters_x000D_
  const defaultOpts = {_x000D_
    a: [1,2,3],_x000D_
    b: true,_x000D_
    c: 0.3289,_x000D_
    d: "str",_x000D_
  }_x000D_
  // merge default and passed-in parameters_x000D_
  // defaultOpts must go first!_x000D_
  const mergedOpts = {...defaultOpts, ...opts};_x000D_
_x000D_
  // you can now refer to parameters like b as mergedOpts.b,_x000D_
  // or just assign mergedOpts.b to b_x000D_
  console.log(mergedOpts.a);_x000D_
  console.log(mergedOpts.b);_x000D_
  console.log(mergedOpts.c);  _x000D_
  console.log(mergedOpts.d);_x000D_
}_x000D_
// the parameters you passed in override the default ones_x000D_
// all JS types are supported: primitives, objects, arrays, functions, etc._x000D_
let var1, var2="random var";_x000D_
foo(var1, var2, {a: [1,2], d: "differentString"});_x000D_
_x000D_
// parameter values inside foo:_x000D_
//a: [1,2]_x000D_
//b: true_x000D_
//c: 0.3289_x000D_
//d: "differentString"
_x000D_
_x000D_
_x000D_

What is spread syntax?

The Rest/Spread Properties for ECMAScript proposal (stage 4) adds spread properties to object literals. It copies own enumerable properties from a provided object onto a new object. More on mdn

Note: spread syntax in object literals doesn't work in Edge and IE and it is an experimental feature. see browser compatability


The best way really depends on the function and the arguments. Each of your options is a good idea in different situations. I generally try these in the following order until one of them works:

  1. Using optional arguments like y = y || 'default'. This is convenient if you can do it, but it may not always work practically, e.g. when 0/null/undefined would be a valid argument.

  2. Using number of arguments. Similar to the last option but may work when #1 doesn't work.

  3. Checking types of arguments. This can work in some cases where the number of arguments is the same. If you can't reliably determine the types, you may need to use different names.

  4. Using different names in the first place. You may need to do this if the other options won't work, aren't practical, or for consistency with other related functions.


For your use case, this is how I would tackle it with ES6 (since it's already the end of 2017):

const foo = (x, y, z) => {
  if (y && z) {
    // Do your foo(x, y, z); functionality
    return output;
  }
  // Do your foo(x); functionality
  return output;
}

You can obviously adapt this to work with any amount of parameters and just change your conditional statements accordingly.


As this post already contains a lot of different solutions i thought i post another one.

function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

function overload() {
   var functions = arguments;
   var nroffunctionsarguments = [arguments.length];
    for (var i = 0; i < arguments.length; i++) {
        nroffunctionsarguments[i] = arguments[i].length;
    }
    var unique = nroffunctionsarguments.filter(onlyUnique);
    if (unique.length === arguments.length) {
        return function () {
            var indexoffunction = nroffunctionsarguments.indexOf(arguments.length);
            return functions[indexoffunction].apply(this, arguments);
        }
    }
    else throw new TypeError("There are multiple functions with the same number of parameters");

}

this can be used as shown below:

var createVector = overload(
        function (length) {
            return { x: length / 1.414, y: length / 1.414 };
        },
        function (a, b) {
            return { x: a, y: b };
        },
        function (a, b,c) {
            return { x: a, y: b, z:c};
        }
    );
console.log(createVector(3, 4));
console.log(createVector(3, 4,5));
console.log(createVector(7.07));

This solution is not perfect but i only want to demonstrate how it could be done.


#Forwarding Pattern => the best practice on JS overloading Forward to another function which name is built from the 3rd & 4th points :

  1. Using number of arguments
  2. Checking types of arguments
window['foo_'+arguments.length+'_'+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments)

#Application on your case :

 function foo(...args){
          return window['foo_' + args.length+'_'+Array.from(args).map((arg)=>typeof arg).join('_')](...args);

  }
   //------Assuming that `x` , `y` and `z` are String when calling `foo` . 
  
  /**-- for :  foo(x)*/
  function foo_1_string(){
  }
  /**-- for : foo(x,y,z) ---*/
  function foo_3_string_string_string(){
      
  }

#Other Complex Sample :

      function foo(...args){
          return window['foo_'+args.length+'_'+Array.from(args).map((arg)=>typeof arg).join('_')](...args);
       }

        /** one argument & this argument is string */
      function foo_1_string(){

      }
       //------------
       /** one argument & this argument is object */
      function foo_1_object(){

      }
      //----------
      /** two arguments & those arguments are both string */
      function foo_2_string_string(){

      }
       //--------
      /** Three arguments & those arguments are : id(number),name(string), callback(function) */
      function foo_3_number_string_function(){
                let args=arguments;
                  new Person(args[0],args[1]).onReady(args[3]);
      }
     
       //--- And so on ....   

You can user the 'addMethod' from John Resig. With this method you can "overload" methods based on arguments count.

// addMethod - By John Resig (MIT Licensed)
function addMethod(object, name, fn){
    var old = object[ name ];
    object[ name ] = function(){
        if ( fn.length == arguments.length )
            return fn.apply( this, arguments );
        else if ( typeof old == 'function' )
            return old.apply( this, arguments );
    };
}

I have also created an alternative to this method that uses caching to hold the variations of the function. The differencies are described here

// addMethod - By Stavros Ioannidis
function addMethod(obj, name, fn) {
  obj[name] = obj[name] || function() {
    // get the cached method with arguments.length arguments
    var method = obj[name].cache[arguments.length];

    // if method exists call it 
    if ( !! method)
      return method.apply(this, arguments);
    else throw new Error("Wrong number of arguments");
  };

  // initialize obj[name].cache
  obj[name].cache = obj[name].cache || {};

  // Check if a method with the same number of arguments exists  
  if ( !! obj[name].cache[fn.length])
    throw new Error("Cannot define multiple '" + name +
      "' methods with the same number of arguments!");

  // cache the method with fn.length arguments
  obj[name].cache[fn.length] = function() {
    return fn.apply(this, arguments);
  };
}

check this out. It is very cool. http://ejohn.org/blog/javascript-method-overloading/ Trick Javascript to allow you to do calls like this:

var users = new Users();
users.find(); // Finds all
users.find("John"); // Finds users by name
users.find("John", "Resig"); // Finds users by first and last name

You can use this methode

function func1(a, b, c) {
  console.log(arguments[0]);
  // expected output: 1

  console.log(arguments[1]);
  // expected output: 2

  console.log(arguments[2]);
  // expected output: 3
}

func1(1, 2, 3);

ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments


I am working on a library that provides class like code capabilities to Javascript, currently it supports constructors, inheritance, methods overload by number of params and by types of params, mixins, statics properties and singleton.

See an example of method overloading using that library:

eutsiv.define('My.Class', {
    constructor: function() {
        this.y = 2;
    },
    x: 3,
    sum: function() {
        return this.x + this.y;
    },
    overloads: {
        value: [
            function() { return this.x + ', ' + this.y },
            function(p1) { this.x = p1; },
            function(p1, p2) { this.x = p1; this.y = p2; }  // will set x and y
        ]
    }
});

var test = new My.Class({ x: 5 });   // create the object
test.value();                        // will return '5, 2'
test.sum();                          // will return 7
test.value(13);                      // will set x to 13
test.value();                        // will return '13, 2'
test.sum();                          // will return 15
test.value(10, 20);                  // will set x to 10 and y to 20
test.value();                        // will return '10, 20'
test.sum();                          // will return 30

Any feedback, bug fixes, docs and tests improves are welcome!

https://github.com/eutsiv/eutsiv.js


I'm not sure about best practice, but here is how I do it:

/*
 * Object Constructor
 */
var foo = function(x) {
    this.x = x;
};

/*
 * Object Protoype
 */
foo.prototype = {
    /*
     * f is the name that is going to be used to call the various overloaded versions
     */
    f: function() {

        /*
         * Save 'this' in order to use it inside the overloaded functions
         * because there 'this' has a different meaning.
         */   
        var that = this;  

        /* 
         * Define three overloaded functions
         */
        var f1 = function(arg1) {
            console.log("f1 called with " + arg1);
            return arg1 + that.x;
        }

        var f2 = function(arg1, arg2) {
             console.log("f2 called with " + arg1 + " and " + arg2);
             return arg1 + arg2 + that.x;
        }

        var f3 = function(arg1) {
             console.log("f3 called with [" + arg1[0] + ", " + arg1[1] + "]");
             return arg1[0] + arg1[1];
        }

        /*
         * Use the arguments array-like object to decide which function to execute when calling f(...)
         */
        if (arguments.length === 1 && !Array.isArray(arguments[0])) {
            return f1(arguments[0]);
        } else if (arguments.length === 2) {
            return f2(arguments[0], arguments[1]);
        } else if (arguments.length === 1 && Array.isArray(arguments[0])) {
            return f3(arguments[0]);
        }
    } 
}

/* 
 * Instantiate an object
 */
var obj = new foo("z");

/*
 * Call the overloaded functions using f(...)
 */
console.log(obj.f("x"));         // executes f1, returns "xz"
console.log(obj.f("x", "y"));    // executes f2, returns "xyz"
console.log(obj.f(["x", "y"]));  // executes f3, returns "xy"

As of July 2017, the following has been the common technique. Note that we can also perform type checking within the function.

function f(...rest){   // rest is an array
   console.log(rest.length);
   for (v of rest) if (typeof(v)=="number")console.log(v);
}
f(1,2,3);  // 3 1 2 3

There is no real function overloading in JavaScript since it allows to pass any number of parameters of any type. You have to check inside the function how many arguments have been passed and what type they are.


The correct answer is THERE IS NO OVERLOADING IN JAVASCRIPT.

Checking / Switching inside the function is not OVERLOADING.

The concept of overloading: In some programming languages, function overloading or method overloading is the ability to create multiple methods of the same name with different implementations. Calls to an overloaded function will run a specific implementation of that function appropriate to the context of the call, allowing one function call to perform different tasks depending on context.

For example, doTask() and doTask(object O) are overloaded methods. To call the latter, an object must be passed as a parameter, whereas the former does not require a parameter, and is called with an empty parameter field. A common error would be to assign a default value to the object in the second method, which would result in an ambiguous call error, as the compiler wouldn't know which of the two methods to use.

https://en.wikipedia.org/wiki/Function_overloading

All suggested implementations are great, but truth to be told, there is no native implementation for JavaScript.


JavaScript is untyped language, and I only think that makes sense to overload a method/function with regards to the number of params. Hence, I would recommend to check if the parameter has been defined:

myFunction = function(a, b, c) {
     if (b === undefined && c === undefined ){
          // do x...
     }
     else {
          // do y...
     }
};

The Typescript Handbook mentions Overloads. While checking types and doing different logic based on results has been mentioned before, this approach defining multiple named functions to work with a typing system might be interesting to readers. Here is how TypeScript achieves creating a function that accepts multiple types of arguments that will direct the function logic to do different things based on incoming arguments and types:

The answer is to supply multiple function types for the same function as a list of overloads. This list is what the compiler will use to resolve function calls. Let’s create a list of overloads that describe what our pickCard accepts and what it returns.

let suits = ["hearts", "spades", "clubs", "diamonds"];

function pickCard(x: { suit: string; card: number }[]): number;
function pickCard(x: number): { suit: string; card: number };
function pickCard(x: any): any {
  // Check to see if we're working with an object/array
  // if so, they gave us the deck and we'll pick the card
  if (typeof x == "object") {
    let pickedCard = Math.floor(Math.random() * x.length);
    return pickedCard;
  }
  // Otherwise just let them pick the card
  else if (typeof x == "number") {
    let pickedSuit = Math.floor(x / 13);
    return { suit: suits[pickedSuit], card: x % 13 };
  }
}

let myDeck = [
  { suit: "diamonds", card: 2 },
  { suit: "spades", card: 10 },
  { suit: "hearts", card: 4 },
];

let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);

With this change, the overloads now give us type checked calls to the pickCard function.

In order for the compiler to pick the correct type check, it follows a similar process to the underlying JavaScript. It looks at the overload list and, proceeding with the first overload, attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload. For this reason, it’s customary to order overloads from most specific to least specific.

Note that the function pickCard(x): any piece is not part of the overload list, so it only has two overloads: one that takes an object and one that takes a number. Calling pickCard with any other parameter types would cause an error.


Here is an approach that allows real method overloading using parameter types, shown below:

Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);

Edit (2018): Since this was written in 2011, the speed of direct method calls has greatly increased while the speed of overloaded methods have not.

It is not an approach I would recommend, but it is a worthwhile thought exercise to think about how you can solve these types of problems.


Here is a benchmark of the different approaches - https://jsperf.com/function-overloading. It shows that function overloading (taking types into account) can be around 13 times slower in Google Chrome's V8 as of 16.0(beta).

As well as passing an object (i.e. {x: 0, y: 0}), one can also take the C approach when appropriate, naming the methods accordingly. For example, Vector.AddVector(vector), Vector.AddIntegers(x, y, z, ...) and Vector.AddArray(integerArray). You can look at C libraries, such as OpenGL for naming inspiration.

Edit: I've added a benchmark for passing an object and testing for the object using both 'param' in arg and arg.hasOwnProperty('param'), and function overloading is much faster than passing an object and checking for properties (in this benchmark at least).

From a design perspective, function overloading is only valid or logical if the overloaded parameters correspond to the same action. So it stands to reason that there ought to be an underlying method that is only concerned with specific details, otherwise that may indicate inappropriate design choices. So one could also resolve the use of function overloading by converting data to a respective object. Of course one must consider the scope of the problem as there's no need in making elaborate designs if your intention is just to print a name, but for the design of frameworks and libraries such thought is justified.

My example comes from a Rectangle implementation - hence the mention of Dimension and Point. Perhaps Rectangle could add a GetRectangle() method to the Dimension and Point prototype, and then the function overloading issue is sorted. And what about primitives? Well, we have argument length, which is now a valid test since objects have a GetRectangle() method.

function Dimension() {}
function Point() {}

var Util = {};

Util.Redirect = function (args, func) {
  'use strict';
  var REDIRECT_ARGUMENT_COUNT = 2;

  if(arguments.length - REDIRECT_ARGUMENT_COUNT !== args.length) {
    return null;
  }

  for(var i = REDIRECT_ARGUMENT_COUNT; i < arguments.length; ++i) {
    var argsIndex = i-REDIRECT_ARGUMENT_COUNT;
    var currentArgument = args[argsIndex];
    var currentType = arguments[i];
    if(typeof(currentType) === 'object') {
      currentType = currentType.constructor;
    }
    if(typeof(currentType) === 'number') {
      currentType = 'number';
    }
    if(typeof(currentType) === 'string' && currentType === '') {
      currentType = 'string';
    }
    if(typeof(currentType) === 'function') {
      if(!(currentArgument instanceof currentType)) {
        return null;
      }
    } else {
      if(typeof(currentArgument) !== currentType) {
        return null;
      }
    } 
  }
  return [func.apply(this, args)];
}

function FuncPoint(point) {}
function FuncDimension(dimension) {}
function FuncDimensionPoint(dimension, point) {}
function FuncXYWidthHeight(x, y, width, height) { }

function Func() {
  Util.Redirect(arguments, FuncPoint, Point);
  Util.Redirect(arguments, FuncDimension, Dimension);
  Util.Redirect(arguments, FuncDimensionPoint, Dimension, Point);
  Util.Redirect(arguments, FuncXYWidthHeight, 0, 0, 0, 0);
}

Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);

The first option really deserves attention cause it's the thing I've come up in quite complex code setup. So, my answer is

  1. Using different names in the first place

With a little but essential hint, names should look different for computer, but not for you. Name overloaded functions like: func, func1, func2.


There are two ways you could approach this better:

  1. Pass a dictionary (associative array) if you want to leave a lot of flexibility

  2. Take an object as the argument and use prototype based inheritance to add flexibility.


There is no real function overloading in JavaScript since it allows to pass any number of parameters of any type. You have to check inside the function how many arguments have been passed and what type they are.


If I needed a function with two uses foo(x) and foo(x,y,z) which is the best / preferred way?

The issue is that JavaScript does NOT natively support method overloading. So, if it sees/parses two or more functions with a same names it’ll just consider the last defined function and overwrite the previous ones.

One of the way I think is suitable for most of the case is follows -

Lets say you have method

function foo(x)
{
} 

Instead of overloading method which is not possible in javascript you can define a new method

fooNew(x,y,z)
{
}

and then modify the 1st function as follows -

function foo(arguments)
{
  if(arguments.length==2)
  {
     return fooNew(arguments[0],  arguments[1]);
  }
} 

If you have many such overloaded methods consider using switch than just if-else statements.


This is an old question but one that I think needs another entry (although I doubt anyone will read it). The use of Immediately Invoked Function Expressions (IIFE) can be used in conjunction with closures and inline functions to allow for function overloading. Consider the following (contrived) example:

var foo;

// original 'foo' definition
foo = function(a) {
  console.log("a: " + a);
}

// define 'foo' to accept two arguments
foo = (function() {
  // store a reference to the previous definition of 'foo'
  var old = foo;

  // use inline function so that you can refer to it internally
  return function newFoo(a,b) {

    // check that the arguments.length == the number of arguments 
    // defined for 'newFoo'
    if (arguments.length == newFoo.length) {
      console.log("a: " + a);
      console.log("b: " + b);

    // else if 'old' is a function, apply it to the arguments
    } else if (({}).toString.call(old) === '[object Function]') {
      old.apply(null, arguments);
    }
  }
})();

foo(1);
> a: 1
foo(1,2);
> a: 1
> b: 2
foo(1,2,3)
> a: 1

In short, the use of the IIFE creates a local scope, allowing us to define the private variable old to store a reference to the initial definition of the function foo. This function then returns an inline function newFoo that logs the contents of both two arguments if it is passed exactly two arguments a and b or calls the old function if arguments.length !== 2. This pattern can be repeated any number of times to endow one variable with several different functional defitions.


You can now do function overloading in ECMAScript 2018 without polyfills, checking var length/type, etc., just use the spread syntax.

_x000D_
_x000D_
function foo(var1, var2, opts){_x000D_
  // set default values for parameters_x000D_
  const defaultOpts = {_x000D_
    a: [1,2,3],_x000D_
    b: true,_x000D_
    c: 0.3289,_x000D_
    d: "str",_x000D_
  }_x000D_
  // merge default and passed-in parameters_x000D_
  // defaultOpts must go first!_x000D_
  const mergedOpts = {...defaultOpts, ...opts};_x000D_
_x000D_
  // you can now refer to parameters like b as mergedOpts.b,_x000D_
  // or just assign mergedOpts.b to b_x000D_
  console.log(mergedOpts.a);_x000D_
  console.log(mergedOpts.b);_x000D_
  console.log(mergedOpts.c);  _x000D_
  console.log(mergedOpts.d);_x000D_
}_x000D_
// the parameters you passed in override the default ones_x000D_
// all JS types are supported: primitives, objects, arrays, functions, etc._x000D_
let var1, var2="random var";_x000D_
foo(var1, var2, {a: [1,2], d: "differentString"});_x000D_
_x000D_
// parameter values inside foo:_x000D_
//a: [1,2]_x000D_
//b: true_x000D_
//c: 0.3289_x000D_
//d: "differentString"
_x000D_
_x000D_
_x000D_

What is spread syntax?

The Rest/Spread Properties for ECMAScript proposal (stage 4) adds spread properties to object literals. It copies own enumerable properties from a provided object onto a new object. More on mdn

Note: spread syntax in object literals doesn't work in Edge and IE and it is an experimental feature. see browser compatability


We made over.js to solve this problem is a very elegant way. You can do:

var obj = {

  /**
   * Says something in the console.
   *
   * say(msg) - Says something once.
   * say(msg, times) - Says something many times.
   */
  say: Over(
    function(msg$string){
      console.info(msg$string);
    },
    function(msg$string, times$number){
      for (var i = 0; i < times$number; i++) this.say(msg$string);
    }
  )

};

There are two ways you could approach this better:

  1. Pass a dictionary (associative array) if you want to leave a lot of flexibility

  2. Take an object as the argument and use prototype based inheritance to add flexibility.


I like @AntouanK's approach. I often find myself offering a function with different numbers o parameters and different types. Sometimes they don't follow a order. I use to map looking the types of parameters:

findUDPServers: function(socketProperties, success, error) {
    var fqnMap = [];

    fqnMap['undefined'] = fqnMap['function'] = function(success, error) {
        var socketProperties = {name:'HELLO_SERVER'};

        this.searchServers(socketProperties, success, error);
    };

    fqnMap['object'] = function(socketProperties, success, error) {
        var _socketProperties = _.merge({name:'HELLO_SERVER'}, socketProperties || {});

        this.searchServers(_socketProperties, success, error);
    };

    fqnMap[typeof arguments[0]].apply(this, arguments);
}

The correct answer is THERE IS NO OVERLOADING IN JAVASCRIPT.

Checking / Switching inside the function is not OVERLOADING.

The concept of overloading: In some programming languages, function overloading or method overloading is the ability to create multiple methods of the same name with different implementations. Calls to an overloaded function will run a specific implementation of that function appropriate to the context of the call, allowing one function call to perform different tasks depending on context.

For example, doTask() and doTask(object O) are overloaded methods. To call the latter, an object must be passed as a parameter, whereas the former does not require a parameter, and is called with an empty parameter field. A common error would be to assign a default value to the object in the second method, which would result in an ambiguous call error, as the compiler wouldn't know which of the two methods to use.

https://en.wikipedia.org/wiki/Function_overloading

All suggested implementations are great, but truth to be told, there is no native implementation for JavaScript.


INTRODUCTION

So far reading through so many answers would give anyone a headache. Anyone trying to know the concept would need to know the following prerequisites.

Function overloading Definition, Function Length property, Function argument property

Function overloading in its simplest form means that a function performs different tasks on the basis of number of arguments that are being passed to it. Notably the TASK1, TASK2 and TASK3 are highlighted below and are being performed on the basis of the number of arguments being passed to the same function fooYo.

// if we have a function defined below
function fooYo(){
     // do something here
}
// on invoking fooYo with different number of arguments it should be capable to do different things

fooYo();  // does TASK1
fooYo('sagar'); // does TASK2
fooYo('sagar','munjal'); // does TAKS3

NOTE - JS does not provide inbuilt ability of function overloading.

Alternative

John E Resig (creator of JS) has pointed out an alternative which uses the above prerequisites to achieve the ability to implement function overloading.

The code below uses a straightforward but naive approach by using if-else or switch statement.

  • evaluates the argument-length property.
  • different values result in invocation of different functions.

_x000D_
_x000D_
var ninja = {_x000D_
  whatever: function() {_x000D_
       switch (arguments.length) {_x000D_
         case 0:_x000D_
           /* do something */_x000D_
           break;_x000D_
         case 1:_x000D_
           /* do something else */_x000D_
           break;_x000D_
         case 2:_x000D_
           /* do yet something else */_x000D_
           break;_x000D_
       //and so on ..._x000D_
    } _x000D_
  }_x000D_
}
_x000D_
_x000D_
_x000D_

Another technique is much more clean and dynamic. The highlight of this technique is the addMethod generic function.

  • we define a function addMethod which is used to add different functions to an object with the same name but different functionalities.

  • below the addMethod function accepts three params object name object, function name name and the function that we want to be invoked fn.

  • Inside addMethod definition var old stores the reference to the previous function being stored by the help of closure - a protective bubble.

_x000D_
_x000D_
function addMethod(object, name, fn) {_x000D_
  var old = object[name];_x000D_
  object[name] = function(){_x000D_
    if (fn.length == arguments.length)_x000D_
      return fn.apply(this, arguments)_x000D_
    else if (typeof old == 'function')_x000D_
      return old.apply(this, arguments);_x000D_
  };_x000D_
};
_x000D_
_x000D_
_x000D_

  • use debugger to understand the code flow.
  • below the addMethod adds three functions which when invoked using ninja.whatever(x) with the number of arguments x which can be anything i.e. either blank or one or more than one invokes different functions as defined while making use of the addMethod function.

_x000D_
_x000D_
var ninja = {};_x000D_
debugger;_x000D_
_x000D_
_x000D_
addMethod(ninja,'whatever',function(){ console.log("I am the one with ZERO arguments supplied") });_x000D_
addMethod(ninja,'whatever',function(a){ console.log("I am the one with ONE arguments supplied") });_x000D_
addMethod(ninja,'whatever',function(a,b){ console.log("I am the one with TWO arguments supplied") });_x000D_
_x000D_
_x000D_
ninja.whatever();_x000D_
ninja.whatever(1,2);_x000D_
ninja.whatever(3);
_x000D_
_x000D_
_x000D_


I am working on a library that provides class like code capabilities to Javascript, currently it supports constructors, inheritance, methods overload by number of params and by types of params, mixins, statics properties and singleton.

See an example of method overloading using that library:

eutsiv.define('My.Class', {
    constructor: function() {
        this.y = 2;
    },
    x: 3,
    sum: function() {
        return this.x + this.y;
    },
    overloads: {
        value: [
            function() { return this.x + ', ' + this.y },
            function(p1) { this.x = p1; },
            function(p1, p2) { this.x = p1; this.y = p2; }  // will set x and y
        ]
    }
});

var test = new My.Class({ x: 5 });   // create the object
test.value();                        // will return '5, 2'
test.sum();                          // will return 7
test.value(13);                      // will set x to 13
test.value();                        // will return '13, 2'
test.sum();                          // will return 15
test.value(10, 20);                  // will set x to 10 and y to 20
test.value();                        // will return '10, 20'
test.sum();                          // will return 30

Any feedback, bug fixes, docs and tests improves are welcome!

https://github.com/eutsiv/eutsiv.js


I often do this:

C#:

public string CatStrings(string p1)                  {return p1;}
public string CatStrings(string p1, int p2)          {return p1+p2.ToString();}
public string CatStrings(string p1, int p2, bool p3) {return p1+p2.ToString()+p3.ToString();}

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

JavaScript Equivalent:

function CatStrings(p1, p2, p3)
{
  var s = p1;
  if(typeof p2 !== "undefined") {s += p2;}
  if(typeof p3 !== "undefined") {s += p3;}
  return s;
};

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

This particular example is actually more elegant in javascript than C#. Parameters which are not specified are 'undefined' in javascript, which evaluates to false in an if statement. However, the function definition does not convey the information that p2 and p3 are optional. If you need a lot of overloading, jQuery has decided to use an object as the parameter, for example, jQuery.ajax(options). I agree with them that this is the most powerful and clearly documentable approach to overloading, but I rarely need more than one or two quick optional parameters.

EDIT: changed IF test per Ian's suggestion


Another way to approach this is by using the special variable: arguments, this is an implementation:

function sum() {
    var x = 0;
    for (var i = 0; i < arguments.length; ++i) {
        x += arguments[i];
    }
    return x;
}

so you can modify this code to:

function sum(){
    var s = 0;
    if (typeof arguments[0] !== "undefined") s += arguments[0];
.
.
.
    return s;
}

JavaScript is untyped language, and I only think that makes sense to overload a method/function with regards to the number of params. Hence, I would recommend to check if the parameter has been defined:

myFunction = function(a, b, c) {
     if (b === undefined && c === undefined ){
          // do x...
     }
     else {
          // do y...
     }
};

there is no actual overloading in JS, anyway we still can simulate method overloading in several ways:

method #1: use object

function test(x,options){
  if("a" in options)doSomething();
  else if("b" in options)doSomethingElse();
}
test("ok",{a:1});
test("ok",{b:"string"});

method #2: use rest (spread) parameters

function test(x,...p){
 if(p[2])console.log("3 params passed"); //or if(typeof p[2]=="string")
else if (p[1])console.log("2 params passed");
else console.log("1 param passed");
}

method #3: use undefined

function test(x, y, z){
 if(typeof(z)=="undefined")doSomething();
}

method #4: type checking

function test(x){
 if(typeof(x)=="string")console.log("a string passed")
 else ...
}

I just tried this, maybe it suits your needs. Depending on the number of the arguments, you can access a different function. You initialize it the first time you call it. And the function map is hidden in the closure.

TEST = {};

TEST.multiFn = function(){
    // function map for our overloads
    var fnMap = {};

    fnMap[0] = function(){
        console.log("nothing here");
        return this;    //    support chaining
    }

    fnMap[1] = function(arg1){
        //    CODE here...
        console.log("1 arg: "+arg1);
        return this;
    };

    fnMap[2] = function(arg1, arg2){
        //    CODE here...
        console.log("2 args: "+arg1+", "+arg2);
        return this;
    };

    fnMap[3] = function(arg1,arg2,arg3){
        //    CODE here...
        console.log("3 args: "+arg1+", "+arg2+", "+arg3);
        return this;
    };

    console.log("multiFn is now initialized");

    //    redefine the function using the fnMap in the closure
    this.multiFn = function(){
        fnMap[arguments.length].apply(this, arguments);
        return this;
    };

    //    call the function since this code will only run once
    this.multiFn.apply(this, arguments);

    return this;    
};

Test it.

TEST.multiFn("0")
    .multiFn()
    .multiFn("0","1","2");

So I really liked this way of doing things that I found in secrets of the javascript ninja

function addMethod(object,name,fn){
  var old = object[name];
  object[name] = function(){
    if (fn.length == arguments.length){
      return fn.apply(this,arguments);
    } else if(typeof old == 'function'){
        return old.apply(this,arguments);
    }
  }
}

you then use addMethod to add overloaded functions to any object. The main confusion in this code for me was the use of fn.length == arguments.length -- this works because fn.length is the number of expected parameters, while arguments.length is the number of parameters that are actually called with the function. The reason the anonymous function has no argument is because you can pass in any number of arguments in javascript and the language is forgiving.

I liked this because you can use it everywhere - just create this function and simply use the method in whatever code base you want.

It also avoids having a ridiculously large if/switch statement, which becomes hard to read if you start writing complex code (the accepted answer will result in this).

In terms of cons, I guess the code is initially a little obscure...but I'm not sure of others?


INTRODUCTION

So far reading through so many answers would give anyone a headache. Anyone trying to know the concept would need to know the following prerequisites.

Function overloading Definition, Function Length property, Function argument property

Function overloading in its simplest form means that a function performs different tasks on the basis of number of arguments that are being passed to it. Notably the TASK1, TASK2 and TASK3 are highlighted below and are being performed on the basis of the number of arguments being passed to the same function fooYo.

// if we have a function defined below
function fooYo(){
     // do something here
}
// on invoking fooYo with different number of arguments it should be capable to do different things

fooYo();  // does TASK1
fooYo('sagar'); // does TASK2
fooYo('sagar','munjal'); // does TAKS3

NOTE - JS does not provide inbuilt ability of function overloading.

Alternative

John E Resig (creator of JS) has pointed out an alternative which uses the above prerequisites to achieve the ability to implement function overloading.

The code below uses a straightforward but naive approach by using if-else or switch statement.

  • evaluates the argument-length property.
  • different values result in invocation of different functions.

_x000D_
_x000D_
var ninja = {_x000D_
  whatever: function() {_x000D_
       switch (arguments.length) {_x000D_
         case 0:_x000D_
           /* do something */_x000D_
           break;_x000D_
         case 1:_x000D_
           /* do something else */_x000D_
           break;_x000D_
         case 2:_x000D_
           /* do yet something else */_x000D_
           break;_x000D_
       //and so on ..._x000D_
    } _x000D_
  }_x000D_
}
_x000D_
_x000D_
_x000D_

Another technique is much more clean and dynamic. The highlight of this technique is the addMethod generic function.

  • we define a function addMethod which is used to add different functions to an object with the same name but different functionalities.

  • below the addMethod function accepts three params object name object, function name name and the function that we want to be invoked fn.

  • Inside addMethod definition var old stores the reference to the previous function being stored by the help of closure - a protective bubble.

_x000D_
_x000D_
function addMethod(object, name, fn) {_x000D_
  var old = object[name];_x000D_
  object[name] = function(){_x000D_
    if (fn.length == arguments.length)_x000D_
      return fn.apply(this, arguments)_x000D_
    else if (typeof old == 'function')_x000D_
      return old.apply(this, arguments);_x000D_
  };_x000D_
};
_x000D_
_x000D_
_x000D_

  • use debugger to understand the code flow.
  • below the addMethod adds three functions which when invoked using ninja.whatever(x) with the number of arguments x which can be anything i.e. either blank or one or more than one invokes different functions as defined while making use of the addMethod function.

_x000D_
_x000D_
var ninja = {};_x000D_
debugger;_x000D_
_x000D_
_x000D_
addMethod(ninja,'whatever',function(){ console.log("I am the one with ZERO arguments supplied") });_x000D_
addMethod(ninja,'whatever',function(a){ console.log("I am the one with ONE arguments supplied") });_x000D_
addMethod(ninja,'whatever',function(a,b){ console.log("I am the one with TWO arguments supplied") });_x000D_
_x000D_
_x000D_
ninja.whatever();_x000D_
ninja.whatever(1,2);_x000D_
ninja.whatever(3);
_x000D_
_x000D_
_x000D_


The Typescript Handbook mentions Overloads. While checking types and doing different logic based on results has been mentioned before, this approach defining multiple named functions to work with a typing system might be interesting to readers. Here is how TypeScript achieves creating a function that accepts multiple types of arguments that will direct the function logic to do different things based on incoming arguments and types:

The answer is to supply multiple function types for the same function as a list of overloads. This list is what the compiler will use to resolve function calls. Let’s create a list of overloads that describe what our pickCard accepts and what it returns.

let suits = ["hearts", "spades", "clubs", "diamonds"];

function pickCard(x: { suit: string; card: number }[]): number;
function pickCard(x: number): { suit: string; card: number };
function pickCard(x: any): any {
  // Check to see if we're working with an object/array
  // if so, they gave us the deck and we'll pick the card
  if (typeof x == "object") {
    let pickedCard = Math.floor(Math.random() * x.length);
    return pickedCard;
  }
  // Otherwise just let them pick the card
  else if (typeof x == "number") {
    let pickedSuit = Math.floor(x / 13);
    return { suit: suits[pickedSuit], card: x % 13 };
  }
}

let myDeck = [
  { suit: "diamonds", card: 2 },
  { suit: "spades", card: 10 },
  { suit: "hearts", card: 4 },
];

let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);

With this change, the overloads now give us type checked calls to the pickCard function.

In order for the compiler to pick the correct type check, it follows a similar process to the underlying JavaScript. It looks at the overload list and, proceeding with the first overload, attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload. For this reason, it’s customary to order overloads from most specific to least specific.

Note that the function pickCard(x): any piece is not part of the overload list, so it only has two overloads: one that takes an object and one that takes a number. Calling pickCard with any other parameter types would cause an error.


For your use case, this is how I would tackle it with ES6 (since it's already the end of 2017):

const foo = (x, y, z) => {
  if (y && z) {
    // Do your foo(x, y, z); functionality
    return output;
  }
  // Do your foo(x); functionality
  return output;
}

You can obviously adapt this to work with any amount of parameters and just change your conditional statements accordingly.


There is no way to function overloading in javascript. So, I recommend like the following by typeof() method instead of multiple function to fake overloading.

function multiTypeFunc(param)
{
    if(typeof param == 'string') {
        alert("I got a string type parameter!!");
     }else if(typeof param == 'number') {
        alert("I got a number type parameter!!");
     }else if(typeof param == 'boolean') {
        alert("I got a boolean type parameter!!");
     }else if(typeof param == 'object') {
        alert("I got a object type parameter!!");
     }else{
        alert("error : the parameter is undefined or null!!");
     }
}

Good luck!


Since JavaScript doesn't have function overload options object can be used instead. If there are one or two required arguments, it's better to keep them separate from the options object. Here is an example on how to use options object and populated values to default value in case if value was not passed in options object.

    function optionsObjectTest(x, y, opts) {
        opts = opts || {}; // default to an empty options object

        var stringValue = opts.stringValue || "string default value";
        var boolValue = !!opts.boolValue; // coerces value to boolean with a double negation pattern
        var numericValue = opts.numericValue === undefined ? 123 : opts.numericValue;

        return "{x:" + x + ", y:" + y + ", stringValue:'" + stringValue + "', boolValue:" + boolValue + ", numericValue:" + numericValue + "}";

}

here is an example on how to use options object


Function overloading in Javascript:

Function overloading is the ability of a programming language to create multiple functions of the same name with different implementations. when an overloaded function is called it will run function a specific implementation of that function appropriate to the context of the call. This context is usually the amount of arguments is receives, and it allows one function call to behave differently depending on context.

Javascript doesn't have built-in function overloading. However, this behaviour can be emulated in many ways. Here is a convenient simple one:

_x000D_
_x000D_
function sayHi(a, b) {_x000D_
  console.log('hi there ' + a);_x000D_
  if (b) { console.log('and ' + b) } // if the parameter is present, execute the block_x000D_
}_x000D_
_x000D_
sayHi('Frank', 'Willem');
_x000D_
_x000D_
_x000D_

In scenarios where you don't know how many arguments you will be getting you can use the rest operator which is three dots .... It will convert the remainder of the arguments into an array. Beware of browser compatibilty though. Here is an example:

_x000D_
_x000D_
function foo (a, ...b) {_x000D_
  console.log(b);_x000D_
}_x000D_
_x000D_
foo(1,2,3,4);_x000D_
foo(1,2);
_x000D_
_x000D_
_x000D_