In JavaScript, abbiamo funzioni ed argomenti che passiamo alle funzioni. Tuttavia, come venga gestito il meccanismo di passaggio dei parametri, non risulta essere molto chiaro. Quando si inizia a programmare ad oggetti, ci si puo' trovare perplessi del motivo per cui a volte dialoghiamo con referenze ed altre volte con valori, in maniera del tutto indipendente dalla nostra volonta'. Quest'ultima affermazione e' quantomai vera nel caso di javascript. Proviamo a dare un occhiata da vicino alle funzioni.

In una funzione JavaScript, quando viene passata una variabile di tipo primitivo, come una stringa od un intero, essa viene passata per "valore". Questo significa che ogni cambiamento a questa variabile avviene all'interno della funzione. Il valore della variabile passante, all'esterno della funzione resta inalterato. Ad esempio:

function myfunction(x)
{
// x e' uguale a 4
x = 5;
// x e' uguale a 5
}

var x = 4;
alert(x); // x e' uguale a 4
myfunction(x);
alert(x); // x e' ancora uguale a 4



La storia si complica, ovviamente, al passaggio di un oggetto "complesso". In questo caso, ogni proprieta' di questo oggetto e' accessibile all'interno della funzione. Nel seguente codice:

function myobject()
{
this.value = 5;
}
var o = new myobject();
alert(o.value); // o.value = 5

function objectchanger(fnc)
{
fnc.value = 6;
}
objectchanger(o);
alert(o.value); // o.value = 6



Cosa succede quando passiamo un oggetto ad una funzione? Potremmo aspettarci che viene passato per referenza, permettendo al metodo di accedere a tutte le parti dell'oggetto, comprese le funzioni o metodi dello stesso. Sfortunatamente, non e' proprio cosi'. Proviamo a vedere il risultato di questo esempio:

function myobject()
{
this.value = 5;
}

myobject.prototype.add = function() {this.value++;}

function objectChanger(fnc)
{
fnc(); // invochiamo la funzione passata come argomento
}

var o = new myobject();
alert(o.value); // o.value = 5
o.add();
alert(o.value); // o.value = 6
objectChanger(o.add);
alert(o.value); // spiacenti!, e' ancora 6



Il problema, in questo caso, risiede nell'uso della keyword this. Essa rappresenta un'abbreviazione veloce per riferci all'oggetto attuale a cui ci stiamo riferendo (contesto). Quando passiamo una funzione come parametro, tuttavia, ogni referenza al contesto iniziale viene perso. Piu' precisamente, in objectChanger this si riferisce al contesto dell'oggetto chiamante e non alla funzione dell'oggetto che abbiamo passato. Per funzioni standalone, potrebbe essere l'oggetto window. Per funzioni chiamate da un evento, potrebbe essere l'oggetto evento. Tutto questo, ovviamente, procura un comportamento non voluto e non standard per un tipico scenario di programmazione ad oggetti.

Ci sono alcuni modi per circoscrivere il problema. Se conosciamo il metodo dell'oggetto che sara' chiamato, il lavoro e' davvero semplice. Basta passare tutto l'oggetto al posto della funzione, chiamando quest'ultima da dentro il nuovo contesto. Riscrivendo l'esempio precedente:

function objectChanger(obj)
{
obj.add(); // chiamiamo il metodo
}
objectChanger(o);
alert(o.value); // o.value = 7



Se non conosciamo il metodo dell'oggetto che stiamo passando, allora sara' necessario passare metodo ed oggetto contemporaneamente come parametri. Per accedere al metodo, useremo il metodo call. Call e' una parte delle specifiche JavaScript e permette ad una funzione di essere avviata nel contesto di un altro oggetto. Come risultato, il selettore this questa volta si riferira' all'oggetto giusto: l'oggetto passato.
Ritornando all'esempio precedente:

function objectChanger(fnc, obj)
{
fnc.call(obj); // avviamo la funzione sul giusto oggetto
}
objectchanger(o.add, o);
alert(o.value); // o.value = 7



JavaScript e' un linguaggio orientato agli oggetti. Il porting di oggetti da altri linguaggi, tuttavia, puo' comportare una riscrittura logica degli stessi per essere pienamente compatibili con il paradigma OOP di JavaScript. Come unica regola fondamentale, bisogna tenere presente che ci stiamo riferendo ad un linguaggio che non utilizza il passaggio per referenza "classico". Al contrario, le referenze vengono passate per valore. Questo significa che la referenza stessa non puo' essere alterata (come succede in C). Soltanto il contenuto dell'oggetto a cui ci si riferisce può essere moficiato. C'e' una grossa differenza tra "passare per referenza" e "passare una referenza per valore". Le tecniche spiegate sopra possono circoscrivere il problema e rendere il linguaggio piu' simile alle realta' OOP conosciute.