Invocazione dinamica di metodi in JavaScript

Spesso scrivendo codice in JavaScript capita di dover richiamare un determinato
metodo a seconda del contesto. Un primo approccio potrebbe essere il seguente:

if (condition) {
  obj.method1(arg1, arg2);
} else {
  obj.method2(arg1, arg2);
}

Altrettanto spesso, però, capita di dover generare dinamicamente il nome del
metodo da invocare, ma non è possibile farlo utilizzando la dot-notation:

//Errore
var obj = new Object,
    nomeMetodo = "method1"; //simulazione della generazione 
                            //dinamica del nome

obj.method1 = function() { 
    console.log("Invocato method1"); 
}

obj.nomeMetodo();
/* TypeError: o.nomeMetodo is not a function
   o.nomeMetodo() 
 */

JavaScript però fornisce anche una sintassi alternativa per l’invocazione dei
metodi, la brackets-notation che, se avete programmato almeno una volta negli
ultimi 50 anni, avrete sicuramente utilizzato per accedere agli elementi di un
Array:

// brackets operator
var arr = [],
    obj = new Object,
    nomeMetodo = "method1";


obj.method1 = function() { 
    console.log("Invocato method1"); 
}

arr.push("zero");
arr.push("uno");
// operatore [] su Array
console.log(arr[1]) //"uno"

//operatore [] su Object
console.log(obj[nomeMetodo]) //"Invocato method1"

Gli utilizzi pratici di questa tecnica sono innumerevoli, soprattutto per
scrivere codice cross-browser. Un esempio.

Tutti i moderni browser supportano gli eventi del DOM Level 2, mentre alcune
versioni precedenti di IE avevano una sintassi diversa, e browser ancora più
vecchi supportavano solo gli eventi del DOM Level 0. Quindi possiamo scrivere
una funzione che astrae queste differenze:

function addListener(element, type, handler) {
    if( element.addEventListener ) { //DOM Level 2 events
        element.addEventListener(type, handler, false);
    } else if ( element.attachEvent ) { // IE < 9
        element.attachEvent("on" + type, handler);
    } else { // Old browser: Level 0!
        element["on" + type] = handler;
    }
}

Utilizzando la capability detection :

  • se gli eventi DOM Level 2 sono supportati, li utilizziamo in fase di
    bubbling,
  • se si tratta di una versione di IE precedente alla 9, utilizziamo la
    sintassi proprietaria,
  • se invece siamo in presenza di un vecchio browser, utilizziamo gli eventi
    DOM Level 0.

In quest'ultimo caso, dato che l'event handler è considerato proprio un metodo associato
all'oggetto, possiamo utilizzare l'operatore [] per creare dinamicamente il
nome del metodo da richiamare, a seconda del tipo dell'evento (es. "click"
diventa "onclick").

3 thoughts on “Invocazione dinamica di metodi in JavaScript

  1. Post interessante. Le due notazioni in realtà derivano dalla natura di ogni cosa in Java. Tutto, di fatto, è una funzione o qualcosa di simile e siccome le funzioni sono esse stessi oggetti, ecco che si può accedere pressochè a tutto via “hash” (square brackets) oppure con la sintassi dotted, che fra l’altro è quella “consigliata” dal verificatore JSLint di Crockford.

    Sostanzialmente: a.b a["b"]

    Non credo si paghi nulla in termini di prestazioni ad usare l’una o l’altra, però effettivamente la dotted mi pare più comoda (anche se il nome della cosa invocata non può ovviamente contenere un punto: serve per forza la squared in quel caso)

    Ciau! ^^

    • Sicuramente la notazione “col punto” è più comoda, però a volte si vedono cose del tipo eval("object."+ methodName ";"); che fanno rabbrividire e sarebbero facilmente evitate con object[methodName];

      Ciao! :)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>