JavaScript: overload dei metodi

JavaScript: overload dei metodi

L'overload dei metodi degli oggetti è una tecnica molto usata nella programmazione orientata agli oggetti in JavaScript. Anni fa John Resig (creatore di jQuery) ha proposto una tecnica molto interessante che vale la pena riportare in questa sede.

Viene definita la seguente funzione:


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 );
    };
}

Alcuni esempi d'uso:


function Users(){
  addMethod(this, "find", function(){
    // Find all users...
  });
  addMethod(this, "find", function(name){
    // Find a user by name
  });
  addMethod(this, "find", function(first, last){
    // Find a user by first and last name
  });
}

O con la proprietà/oggetto prototype:


function Users(){}
addMethod(Users.prototype, "find", function(){
  // Find all users...
});
addMethod(Users.prototype, "find", function(name){
  // Find a user by name
});
addMethod(Users.prototype, "find", function(first, last){
  // Find a user by first and last name
});

Risultati:


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
users.find("John", "E", "Resig"); // Does nothing 

Resig ci avverte che:

  • The overloading only works for different numbers of arguments - it doesn't differentiate based on type, argument names, or anything else. (ECMAScript 4/JavaScript 2, however, will have this ability - called Multimethods - I'm quite excited.)
  • All methods will some function call overhead. Thus, you'll want to take that into consideration in high performance situations.

Per questi motivi la funzione può essere riscritta come segue:


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