sabato, novembre 15, 2014

Spaghetti o Ravioli?

Siamo ora pronti a comprendere il codice presentato nel primo post, lo riscrivo qui per comodità

  var modulo = (function() {  
                   var f1 = function() {  
               
                            },  
                       f2 = function() {  
                 
                            },  
                       f3 = function() {  
                 
                            };  
               
                       return {  
                         f1 : f1,  
                         f2 : f2,
                         f3 : f3
                       };   
                })();  
   

Cosa contiene la variabile modulo? Contiene il risultato della esecuzione immediata della funzione dichiarata a destra, tale funzione ritorna il seguente oggetto


 {  
   f1 : function() {},  
   f2 : function() {}  
 }  
   
   

e quindi window.modulo espone le uniche proprietà f1 e f2 che in questo caso sono funzioni.

Le inner function, cioe le funzioni dichiarate all'interno di un'altra funzione, hanno l'importante proprietà di poter accedere alle variabili locali e i parametri dell'outer function anche quando l'outer function ha terminato la sua esecuzione.

Questa caratteristica, chiamata closure, insieme al concetto di  IIFE: Immediate Invocation Function Expression,  acronimo pomposo per descrivere una funzione che viene invocata appena subito dopo la sua dichiarazione, permette di creare degli oggetti che espongono solo le funzioni che vogliamo, nascondendo i dettagli implementativi; ciò ci permette di modularizzare il nostro codice, passando da un codice a spaghetti a un codice a ravioli :)

Facciamo ancora un esempio:

 var biblioteca = (function(nome) {  
        
      var libri = [],  
       
           nomeBiblioteca = nome,  
          
           inserisciLibro = function(libro) {  
               libri.push(libro);  
           },  
          
           getNomeBiblioteca = function() {  
               return nomeBiblioteca;  
           },  
          
           numeroLibri = function() {  
               return libri.length;  
           };  
   
          return {  
            insert : inserisciLibro,  
            getName : getNomeBiblioteca,  
            length : numeroLibri  
          };  
   
 })('civica di milano');  


 biblioteca.insert({titolo:'guerra e pace'});
 console.log(biblioteca.getName());
 console.log(biblioteca.length());

biblioteca è un oggetto, ritornato dalla funzione che viene immediatamente eseguita, espone dunque solo i tre metodi insert, getName, e length.

La variabile locale libri non è accessibile dall'esterno, essendo una variabile locale di una funzione,

I metodi dell'oggetto ritornato, possono ancora accedere alle variabili locali della funzione esterna, anche se la funzione esterna ha già finito la sua esecuzione: notate bene che in questo caso la eseguiamo immediatamente passandole il parametro 'civica di milano'.

Le linee di codice successive, memorizzano il libro dal titolo 'guerra e pace' nell'array libri, che esiste ancora nonostante la funzione precedente ha finito la sua esecuzione, stampano sulla console rispetivamente 'civica di milano' e 1.

Spero che ora non abbiate più dubbi sul potente concetto di closure, che ci permette di definire oggetti complessi nascondendo la loro complessita a chi deve utilizzarli.

Cominciate a utilizzare le IIFE e il vostro codice passerà da un groviglio di spaghetti a dei ravioli gustabili  uno ad uno :).

Alla prox.
Ivan

1 commento:

  1. Ciao grazie per l'articolo, ho una domanda però... perchè l'oggetto del primo esempio non ha f3?

    {
    f1 : function() {},
    f2 : function() {},
    f3 : function() {}
    }

    RispondiElimina