Function Overloader //JavaScript Repository

Description

Allows functions to be overloaded (different versions of the same function are called based on the arguments types).
Created: 2005.11.01 - Modified 2006.11.29

Code (Download)

//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/classes/overloader [rev. #2]

Overloader = function(){
    var f = function(args){
        var i, l, h = "", empty = {};
        for(i = -1, l = (args = [].slice.call(arguments)).length; ++i < l;)
            args[i] !== undefined && args[i] !== null ? h += args[i].constructor : empty[i] = 1;
        if(!(h = f._methods[h])){
            var x, j, k, m = -1;
            for(i in f._methods){
                for(k = 0, j = -1, l = Math.max(args.length, x = f._methods[i][1]); ++j < l;
                    !empty[j] && (args[j] instanceof x[j] || args[j].constructor == x[j]) && ++k);
                k > m && (h = f._methods[i], m = k);
            }
        }
        return h ? h[0].apply(f, args) : undefined;
    };
    f._methods = {};
    f.overload = function(f, args){
        this._methods[(args = [].slice.call(arguments, 1)).join("")] = [f, args];
    };
    f.unoverload = function(args){
        return delete this._methods[[].slice.call(arguments).join("")];
    };
    return f;
};

Example (Example)

<script type="text/javascript">
//<![CDATA[

//adds overloading support to the variable func
func = new Overloader;

//adds a version that receives an argument of the type Number
func.overload(function(x){
    document.write("Receives: NUMBER<br />");
}, Number);

//String
func.overload(function(x){
    document.write("Receives: STRING<br />");
}, String);

//version that receives 2 arguments, Function and Number
func.overload(function(x,y){
    document.write("Receives: FUNCTION, NUMBER<br />");
}, Function, Number);

//Number and String
func.overload(function(x,y){
    document.write("Receives: NUMBER, STRING<br />");
}, Number, String);

//test calls
func(function(){}, 123);
func(123);
func("ABC");
func(123, "ABC");

/*when there's no version with the required argument types, it searches for the best match,
the function which has more similar arguments, if two or more functions have the same "score",
it calls the one that was overloaded first*/
func({});

//removes the first function that was overloaded
func.unoverload(Number);

//as there's no function that receives an "Object", the first function will be called
//again, but as we removed the "Number" handler, the next in the list is the one that receives a "String"
func({});

//]]>
</script>

Help

Constructor

Overload(void)
Returns a callable function able to be overloaded.

Methods

Overloader.overload(handler: Function, [argType0: Type, argType1: Type, ...]): void
Overloads the object with a new function given the arguments types.
handler
function that will be overloaded
argType0: Type, argType1: Type, ...
specifies the arguments types that the function defined in "handler" expects, if nothing is informed, the function assumes that "handler" doesn't receive arguments, you can use the default types (String, Number, Object, etc) as well as the types defined by you (a class...)
Overloader.unoverload([argType0: Type, argType1: Type, ...]): Boolean
Unoverloads a function for which the arguments types combine perfectly, retorns "true" in case of success.
argType0: Type, argType1: Type, ...
specifies the arguments types that the function to be removed expects

Rank (Votes: 17)

4.18