Il costruttore Function è davvero molto importante nella programmazione Javascript, dato che le funzioni costituiscono spesso un'ampia parte delle nostre applicazioni.
MooTools ne estende l'oggetto prototype con metodi fondamentali, in una elegante modalità object-oriented che ci permette di lavorare direttamente sui riferimenti alle nostre funzioni.
Partiamo dal metodo della classe Function più utilizzato, che risponde al nome di bind
. A chi di voi non è mai capitato di avere problemi di scope? Bene, con il metodo bind
questo problema non si pone più, dato che siamo noi a controllare chi assumerà il ruolo di "this" all'interno delle nostre funzioni. Vediamo subito un esempio:
// una normale funzione. Ora "this" si riferisce a window function setDisplay(){ this.setStyle('display', 'block'); }; // un elemento var element = $('myElement'); // il riferimento alla funzione alla quale è stato effettuato il "binding". Ora "this" si riferisce ad element var boundSetDisplay = setDisplay.bind(element); // l'elemento con id 'myElement' assume il ruolo di 'this' all'interno della funzione 'setDisplay' // richiamando la versione a cui è stato effettuato il binding, la proprietà display dell'elemento assumerà il valore 'block' boundSetDisplay();
Ricordate, bind
è un metodo molto importante e spesso troverete l'esigenza reale di utilizzarlo.
Il metodo bindWithEvent
, oltre a permettere il "binding", crea una sorta di "spazio" per l'oggetto Event all'interno di una funzione, trasformandola di fatto in un perfetto gestore di eventi che possiamo impostare ai nostri elementi:
// funzione listener function listener(event, word) { alert(event.target); this.set('html', word); } // funzione listener in versione "gestore degli eventi" var boundListener = listener.bindWithEvent(myDiv, 'Function Called!'); // agganciamo il gestore all'evento click myDiv.addEvent('click', boundListener);
Anche i metodi pass
, attempt
e run
permettono di lavorare con i riferimenti alle nostre funzioni. Con pass
possiamo ottenere un riferimento alla nostra funzione passando gli argomenti desiderati sotto forma di array ("closure"), mentre con attempt
possiamo tentare di azionare una funzione che restituirà il risultato o null in caso di fallimento. Run
infine svolge il compito del metodo nativo apply
, anche se gli argomenti che riceve sono invertiti (e può ricevere un solo argomento come parametro per la funzione):
// Function::pass var myFunction = function(){ for (var i = 0, l = arguments.length; i < l; i++){ alert(i + ': ' + arguments[i]); } } // restituiamo il riferimento alla funzione 'myFunction' prima con un solo argomento e poi con 3 argomenti var oneArg = myFunction.pass('Blue'); // successivamente... oneArg(); var threeArgs = myFunction.pass(['Blue', 'Red', 'Green']); // successivamente... threeArgs(); // Function::attempt var myObj = {'red': 'hot'}; var myFunction = function(){ for (var i = 0; i < arguments.length; i++){ if(!this[arguments[i]]) throw('Exception!'); } }; // result = false var result = myFunction.attempt(['red', 'blue'], myObj); // Function::run var myFunction = function(a, b, c){ return a + b + c; } myFunction.run([1,2,3]);
I metodi delay
e periodical
, infine, svolgono il compito delle funzioni globali setTimeout
e setInterval
, in una versione molto più pratica (permettono il "binding" e il passaggio di argomenti tramite array) ed elegante. Restituiscono il riferimento rispettivamente al timeout e all'intervallo impostati:
function myFunction() { alert('Function called!'); } // attendiamo 1 secondo e richiamiamo la nostra funzione var timeout = myFunction.delay(1000); // richiamiamo la funzione 'myFunction' ogni secondo var interval = myFunction.periodical(1000);
Conclusione
In questa lezione abbiamo osservato come possiamo alterare il comportamento delle nostre funzioni in base alle nostre esigenze ed ottenere cosi nuove e più flessibili funzionalità. Ricordo infine che la maggior parte dei metodi presentati in questa lezione, nascono dal metodo create
(anch'esso del costruttore Function) che può essere usato singolarmente per unificare i diversi compiti offerti dai rispettivi metodi.