Sunday, September 9, 2012

Method Overloading in JavaScript

We are all aware of method overloading as a concept, Which states we can have same function name with different arguments. Lets see how can we achieve it in JavaScript.
Before starting on overloading , lets see how length property works on function, because we will need to use that property while building overloading -
function myfunc1(){}
function myfunc2(arg1){}
function myfunc3(arg1,arg2){}
alert(myfunc1.length); --> 0
alert(myfunc2.length); --> 1
alert(myfunc3.length); --> 2

using length property we can identify how many arguments are passed to the function.

Now let try to implement overloading
function addMethod(object,name,fn){
    var old = object[name];
    object[name] = function() {
        if(fn.length == arguments.length) {
            fn.apply(object, arguments);
        }
        else if(typeof(old) == 'function') {
            old.apply(object,arguments);
        }
    }
}
Just to clarify addMethod is not inbuilt method in JavaScript. We are writing our own method to achieve overloading.
If we see this method it take 3 arguments- object, name and fn.
object - the object on which we want to execute this method.
name - name of the function we want to overload.
fn - definition of function.

addMethod if you notice check the number of arguments and depending upon that it will identify if you have any method with the given name and same number of arguments, then it execute it.
To understand it more lets try to use it -
 function Person(){
    addMethod(this,'find',function(){
        alert('hi 0');
    });
    addMethod(this,'find',function(arg1){
        alert('hi 1')
    });
    addMethod(this,'find',function(arg1,arg2){
        alert('hi 2');
    })
}

var p = new Person();
p.find();
p.find('a');
p.find('a','b');

In above code once we create Person object, we are adding 3 new properties to Person, all has name find, but have different signature. In the addMethod, it appends these properties to person object. Once i call p.find(), it will try to find if Person has any function with name find and have 0 arguments in it. It will loop in that object until it finds it. If the function does not exist, it will exit.
If you attach a debugger and check the addMethod while execution you will find the first run we find argument.length as 0 and fn.length as 2(which is 3rd function), then it execute old.apply again and get the other find object, where it gets fn.length as 1 and finally as 0. Once it get the match it execute the find function.
Here we can not use call instead of apply, as the arguments are passed in the format of array.

Here is the whole code which executes different find methods in Person object-
function addMethod(object,name,fn){
    var old = object[name];
    object[name] = function() {
        if(fn.length == arguments.length) {
            fn.apply(object, arguments);
        }
        else if(typeof(old) == 'function') {
            old.apply(object,arguments);
        }
    }
}

function Person(){
    addMethod(this,'find',function(){
        alert('hi 0');
    });
    addMethod(this,'find',function(arg1){
        alert('hi 1')
    });
    addMethod(this,'find',function(arg1,arg2){
        alert('hi 2');
    })
}

var p = new Person();
p.find();
p.find('a');
p.find('a','b');

No comments:

Post a Comment