Javascript function overloading

I was reading a post yesterday about function overloading in javascript, and the suggested solution had quite a performance overhead when used with multiple signatures.
In addition, it only used the number of arguments, and not their types and order to distinguish between the signatures.

For some reason I woke up early this morning with a solution to this.
The following code will do all of the above and has the same overhead for all number of signatures.

//returns an overloadable method
Function.CreateOverloaded = function(){
    var overloads = [];
    //creates the overloaded method
    var func = function(){
        var sign = [];
        for (var i=0;i < arguments.length; i++) {
            sign.push(typeof arguments[i]);
        }
        sign = sign.join();
        var func = overloads["(" + sign + ")"];
        if (!func) {throw "No matching signature";}
        return func.apply(this, arguments);
    };

    //method for adding a function with a spesific signature
    func.AddSignature = function(func, sign){
        if (overloads["(" + sign + ")"]){throw "Duplicate signature"};
        overloads["(" + sign + ")"] = func;
    };
    return func;
}

To test it you can use the following code

var myFunc = Function.CreateOverloaded();
myFunc.AddSignature(function(){
    alert("test1");
}, "");
myFunc.AddSignature(function(var){
    alert(var);
}, "string");
myFunc.AddSignature(function(integer){
    alert(integer + "x 5 = " + (integer * 5));
}, "number");
myFunc.AddSignature(function(int1, int2){
    alert(int1 * int2);
}, "number,number");
myFunc.AddSignature(function(string, int){
    alert(string + " equals " + int);
}, "string,number");

myFunct();
myFunc("test2")
myFunc(3);
myFunc(3, 5);
myFunc("five", 5);

Tags: ,

This entry was posted on Thursday, November 15th, 2007 at 10:00 and is filed under programming, Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

  • http://weblogs.asp.net/bleroy Bertrand Le Roy

    I think this suffers from the same problems as John Resig’s suggestion and some more. It’s inconvenient to have to specify the signature at two different places: there’s considerable risk for typos (especially as the code is not very resilient to stuff like spaces) and the two versions of the signatures are at different places, making management more difficult. Relying on typeof to determine the type limits you to the handful of types it supports and does nothing for the richer type systems that JS allows and that are now widely used. And of course, the performance overhead is still there as there is heavy use of the arguments pseudo-array (which has horrendous performance), an additional level of indirection, and quite a lot of code to execute on every single function call. And of course tooling and reflection scenarios are just killed by all that.

    Again, the real question is do we really think we need overloading that badly? My personal take is that we don’t.

  • http://weblogs.asp.net/bleroy Bertrand Le Roy

    I think this suffers from the same problems as John Resig’s suggestion and some more. It’s inconvenient to have to specify the signature at two different places: there’s considerable risk for typos (especially as the code is not very resilient to stuff like spaces) and the two versions of the signatures are at different places, making management more difficult. Relying on typeof to determine the type limits you to the handful of types it supports and does nothing for the richer type systems that JS allows and that are now widely used. And of course, the performance overhead is still there as there is heavy use of the arguments pseudo-array (which has horrendous performance), an additional level of indirection, and quite a lot of code to execute on every single function call. And of course tooling and reflection scenarios are just killed by all that.

    Again, the real question is do we really think we need overloading that badly? My personal take is that we don’t.

  • http://www.kinsey.no/ oyvind.kinsey

    @Bertrand
    I’m not quite sure what you mean by having to specify the signature at two different places, as this is only done when adding the overload.
    As of typeof’s limitation this was only some code I made to show that it was indeed possible to quite easily make typespecific overloads.

    To extend it to custom object types one could use a method similar to that used in ASP.NET AJAX to check the type of arguments.
    Off course, this would create additional overhead and more code to execute, but hey, thats what you get if you absolutely need typespesific overloading.

    I would not use this code myself in production as its easier to just have different method names.
    So about overloading in general I’m with you, I don’t need it.

  • http://oyvind.kinsey.no/ oyvind.kinsey

    @Bertrand
    I’m not quite sure what you mean by having to specify the signature at two different places, as this is only done when adding the overload.
    As of typeof’s limitation this was only some code I made to show that it was indeed possible to quite easily make typespecific overloads.

    To extend it to custom object types one could use a method similar to that used in ASP.NET AJAX to check the type of arguments.
    Off course, this would create additional overhead and more code to execute, but hey, thats what you get if you absolutely need typespesific overloading.

    I would not use this code myself in production as its easier to just have different method names.
    So about overloading in general I’m with you, I don’t need it.