Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 14
  1. #1
    Utente di HTML.it
    Registrato dal
    Nov 2002
    Messaggi
    412

    Variabile dichiarata all'interno di una funzione che in realtà non esiste che finefa?

    Scusate il titolo un po' ambiguo, ma sta di fatto che ambiguo è di per se il codice in cui mi son imbattuto seguendo il libro Javascript: The Complete Guide (il codice di per sé funziona egregiamente, ma a me serve capire la logica di COME funziona).


    Codice PHP:
    var whenReady = (function()
                      { 
                         var 
    funcs = []; // The functions to run when we get an event
                         
    var ready false// Switches to true when the handler is triggered                            
                    
                                   
    [...]
                                                        
                          
    // Return the whenReady function
                        
    return function whenReady(f
                         {
                            if (
    readyf.call(document); // If already ready, just run it
                             
    else funcs.push(f); // Otherwise, queue it for later.
                         
    }
                                  
                      }());




    whenReady(function() 
               {
                  var 
    clock document.getElementById("clock"); // The clock element
                  
    var icon = new Image(); // An image to drag
                  
    icon.src "clock-icon.png"// Image URL
                 
    [....]
              } 
    Ora capisco che whenReady assume praticamente il valore di
    if (ready) f.call(document);
    else funcs.push(f);


    ma nel frattempo le variabili ready e funcs, necessarie al funzionamento del codice, dove sono memorizzate?

  2. #2
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Originariamente inviato da American
    ma nel frattempo le variabili ready e funcs, necessarie al funzionamento del codice, dove sono memorizzate?
    All'interno dello scope della funzione lambda.
    Tutto ciò che fai con jQuery puoi farlo meglio e con la metà del codice in puro JavaScript.

  3. #3
    Utente di HTML.it
    Registrato dal
    Nov 2002
    Messaggi
    412
    ed in questo caso lo scope include anche la funzione whenReady? Altrimenti non mi spiego come faccia a richiamarle ( if (ready), else funcs.push )

    Inoltre tali variabili sono tracciabili dall'esterno dello scope, ad esempio dal codice principale?

  4. #4
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Originariamente inviato da American
    ed in questo caso lo scope include anche la funzione whenReady? Altrimenti non mi spiego come faccia a richiamarle ( if (ready), else funcs.push )
    Il codice purtroppo crea un po' di confusione. In JavaScript c'è sempre una grossa distinzione tra nome di una funzione e una variabile contenente una funzione.

    Fare:

    codice:
    function miaFunzione () {
      // fai qualcosa
    }
    non è la stessa cosa che fare:

    codice:
    var miaFunzione = function () {
      // fai qualcosa
    };
    Nel primo caso miaFunzione è il nome di una funzione, nel secondo caso è il nome di una variabile.

    Per tornare al tuo esempio… Si tratta di una closures. Segnati quanto segue:
    Ogni qualvolta venga creata una funzione B all'interno di una funzione A e B sia accessibile al return di A (entrambe queste condizioni devono essere vere) la funzione A non viene "distrutta" al termine della sua esecuzione, ma viene lasciata aperta (si parla in questo caso di closures). Non tutte le volte che una funzione è annidata all'interno di un altra si verificano le closures. Perché avvenga è necessario che la funzione annidata risulti in un modo o nell'altro accessibile all'esterno, come ad esempio in questo caso:

    codice:
    function A () {
      return function B () {
        // fai qualcosa
      };
    }
    oppure:

    codice:
    var mioOggetto = {};
    
    function A () {
      mioOggetto.miaFunzione = function () {
        // fai qualcosa
      };
    }
    In entrambi questi casi la funzione annidata risulta accessibile in qualche modo dall'esterno al termine dell'esecuzione della funzione A. Di conseguenza la funzione A resterà aperta fin quando non distruggerai ogni accesso esterno alla funzione interna (closure). Ma annidare una funzione dentro l'altra non comporta di per sé una closure. Ad esempio nel seguente codice non si verificherà una closure, perché non restituisci all'ambiente esterno la funzione annidata (ma ti limiti a utilizzarla):

    codice:
    function quadratoDellaSomma (a, b) {
      function somma (addendo1, addendo2) {
        return addendo1 + addendo2;
      }
      return Math.pow(somma(a, b), 2);
    }
    Le closures si verificano solo ed esclusivamente con le funzioni, non con gli oggetti in generale (a meno che questi non contengano a loro volta funzioni annidate localmente, ovviamente). Tutto chiaro?



    Originariamente inviato da American
    Inoltre tali variabili sono tracciabili dall'esterno dello scope, ad esempio dal codice principale?
    Assolutissimamente NO. È proprio per non "sporcare" l'ambiente globale che si procede così.
    Tutto ciò che fai con jQuery puoi farlo meglio e con la metà del codice in puro JavaScript.

  5. #5
    Utente di HTML.it
    Registrato dal
    Nov 2002
    Messaggi
    412
    Grazie x la spiegazione, adesso mi è tutto un più chiaro

    L'unica cosa che non ho capito è questa

    Il codice purtroppo crea un po' di confusione. In JavaScript c'è sempre una grossa distinzione tra nome di una funzione e una variabile contenente una funzione.
    Qual è la differenza? Il codice in esame richiama la funzione whenReady (riferendosi alla variabile e non alla funzione inizializzata col return, questo l'ho capito), allo stesso modo in cui si chiamerebbe una normale funzione tramite il relativo nome.


    Inoltre sempre con il codice in esame, se la funzione whenReady inizializzata col retun non avesse fatto uso delle variabili ready e funcs, si sarebbe ugualmente verificata una clousure col codice soprastante?

  6. #6
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Originariamente inviato da American
    Qual è la differenza? Il codice in esame richiama la funzione whenReady (riferendosi alla variabile e non alla funzione inizializzata col return, questo l'ho capito), allo stesso modo in cui si chiamerebbe una normale funzione tramite il relativo nome.
    Le differenze sono sottigliezze. All'uso pratico nel 99% dei casi non c'è nessuna differenza. La differenza la noti solo nel caso delle funzioni ricorsive…

    codice:
    function tizio () {
    	// fai qualcosa
    }
    
    var caio = function sempronio () {
    	// questo alert funziona:
    	alert(sempronio);
    };
    
    var altraFunzione = function () {
    	// fai qualcosa
    };
    
    caio();
    alert(sempronio); // questo alert non funziona! (ReferenceError: sempronio is not defined)

    Originariamente inviato da American
    Inoltre sempre con il codice in esame, se la funzione whenReady inizializzata col retun non avesse fatto uso delle variabili ready e funcs, si sarebbe ugualmente verificata una clousure col codice soprastante?
    Sì! Perché ci sono altre variabili intrinseche della funzione madre che devono essere rese disponibili alla funzione annidata (come this, arguments e la funzione stessa).
    Nel momento in cui una funzione dichiarata all'interno di un'altra è resa disponibile all'esterno si crea una closure, a prescindere da come le funzioni sono costruite. Se invece è inaccessibile all'esterno il garbage collector dell'interprete la distrugge seduta stante.
    Ci sono casi in cui la funzione annidata è resa disponibile all'esterno senza che ce ne rendiamo conto. Considera quest'esempio:

    codice:
    function creaTimer () {
    	function saluto () {
    		alert("Ciao mondo!");
    	}
    	setTimeout(saluto , 2000);
    }
    
    creaTimer();
    A ben vedere non c'è modo di chiamare dall'esterno la funzioncina di nome "saluto" contenente l'alert. Eppure la funzione creaTimer() verrà tenuta comunque aperta per due secondi di modo che possa accedervi il timer setTimeout(), dopodiché verrà chiusa. Ci sono insomma casi in cui creiamo closures senza rendercene conto (il che non è bene se ci teniamo a ottimizzare le risorse).

    Una cosa interessante è che se invece annidi una funzione costruita tramite il costruttore di funzioni Function dentro un'altra funzione, non crei mai una closure, perché il costruttore di funzioni non può accedere al local scope:

    codice:
    function creaTimer () {
    	// NON creo closures
    	var saluto = new Function("alert(\"Ciao mondo!\");");
    	setTimeout(saluto , 2000);
    }
    
    creaTimer();
    Tieni però presente che costruire una funzione tramite il costruttore di funzioni è più dispendioso che farlo tramite una dichiarazione letterale. Va fatto solo se ce n'è veramente bisogno!

    Conclusione. Le closures se ben usate possono essere un'importante e potentissima risorsa. Se abusate sono tra le cose che più occupano memoria tra tutte quelle che possiamo fare in JavaScript. N.B. È possibile creare delle closures soft, un po' meno dispendiose di risorse, tramite l'operatore let.

    Spero di essere stato abbastanza esaustivo…
    Tutto ciò che fai con jQuery puoi farlo meglio e con la metà del codice in puro JavaScript.

  7. #7
    Utente di HTML.it
    Registrato dal
    Nov 2002
    Messaggi
    412
    capito grazie

    Ma quello delle closures comunque è un fenomeno di tutti i linguaggi, mica solo di JS, giusto?

  8. #8
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Originariamente inviato da American
    Ma quello delle closures comunque è un fenomeno di tutti i linguaggi, mica solo di JS, giusto?
    No, non di tutti. Se ad esempio programmi in bash e dichiari una funzione dentro un'altra funzione la funzione annidata verrà comunque salvata nel global scope. Tra l'altro quella di usare la sintassi seguente per non "sporcare" il global scope:

    codice:
    (function () {
    	var variabileLocale1 = "Ciao";
    	var variabileLocale2 = "Mondo";
    	// etc. etc.
    })();
    è solo una prassi dovuta all'esistenza di un browser come Internet Explorer, che non supporta l'operatore let. La via "ufficiale" (nonché la meno dispendiosa e la più performante) per il block scoping in JavaScript è infatti la seguente:

    codice:
    <script type="application/javascript;version=1.7">
    
    var esempio = "Ciao";
    
    let (esempio) {
    
    	esempio = "Mondo";
    	alert(esempio); // "Mondo"
    
    }
    
    alert(esempio) // "Ciao"
    
    </script>
    Tutto ciò che fai con jQuery puoi farlo meglio e con la metà del codice in puro JavaScript.

  9. #9
    Utente di HTML.it
    Registrato dal
    Nov 2002
    Messaggi
    412
    Comunque alla fine del discorso, basandomi su quel che posso dedurre, non vedo il motivo del perchè uno debba consapevolmente crearsi delle clousures..

    Spiego: considerando che le variabili rimangono in memoria, tanto vale renderle global scope per e "riciclarle" in altre funzioni. Nel caso del ready di inizio topic ad esempio, si tratta di una variabile che viene utilizzata all'apertura della pagina per poi restare in memoria senza alcun motivo e senza possibilità di sfruttarla in altri modi
    o no?

  10. #10
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Ci sono mille motivi per volere o per non volere variabili globali. Ci sono poi casi in cui non è matematicamente possibile usare variabili globali e si devono per forza usare variabili locali: come nelle funzioni ricorsive, pena il non funzionamento.
    Originariamente inviato da American
    Nel caso del ready di inizio topic ad esempio, si tratta di una variabile che viene utilizzata all'apertura della pagina per poi restare in memoria senza alcun motivo e senza possibilità di sfruttarla in altri modi
    o no?
    Esatto.
    Tutto ciò che fai con jQuery puoi farlo meglio e con la metà del codice in puro JavaScript.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.