Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2019
    Messaggi
    41

    [jQuery]anonymous self-invoking function e anonymous function document.ready

    Salve a tutti ho un dubbio riguardo le funzioni anonime di self-invoking che vengono eseguite immediatamente non appena vengono rilevate da JavaScript e document.ready dove la funzione viene eseguita solo quando il documento (DOM) è completamente caricato e sicuro da manipolare. Mi chiedo quale utilizzare se l'anonymous self-invoking o l'anonymous document.ready. Qui riporto 2 esempi di codice.

    codice:
    (function($) {
                function code...
            })(jQuery);
    Nel primo esempio la funzione anonima viene eseguita immediatamente non appena viene rilevata da JavaScript senza attendere il caricamento completo del documento (DOM).

    codice:
    $(function() {
                function code...
            });
    Nel secondo esempio la funzione anonima è una scorciatoia di document.ready e viene eseguita solo quando il documento (DOM) è completamente caricato e sicuro da manipolare. Tra questi 2 esempi quale è meglio utilizzare? Se in una pagina gli elementi DOM sono già definiti nel codice HTML è meglio utilizzare l'anonymous self-invoking e invece se gli elementi del DOM sono creati dinamicamente durante il caricamento è meglio utilizzare l'anonymous document.ready? Ho questo dubbio nella mia testa e non saprei quale utilizzare .

  2. #2
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    Ciao, mi pare siano due soluzioni non comparabili per un unico specifico problema. Provo a fare un po' di chiarezza; come tu hai affermato, si tratta di due metodi usati generalmente per scopi differenti.

    funzioni anonime di self-invoking che vengono eseguite immediatamente non appena vengono rilevate da JavaScript e document.ready dove la funzione viene eseguita solo quando il documento (DOM) è completamente caricato e sicuro da manipolare
    C'è però da aggiungere che il primo caso (con riferimento al codice da te riportato) non solo è una funzione self-invoking ma si tratta, nello specifico, di una tecnica usata per evitare conflitti con altre librerie che usano la stessa variabile ($) come oggetto principale. Tant'è che nell'argomento della funzione viene passato il riferimento all'oggetto jQuery; per cui, dentro tale funzione, si è sicuri che la variabile $ (argomento della funzione) corrisponda a jQuery e non ad altre librerie eventualmente caricate nello stesso documento.

    Qui un riferimento: Avoiding Conflicts with Other Libraries

    Il secondo caso, come tu stesso hai indicato, serve per avere certezza che gli elementi del DOM siano stati creati, dopo l'apertura della pagina, e quindi manipolabili da script.

    L'uso di uno o dell'altro metodo va esaminato in base allo specifico contesto in cui vuoi che sia eseguito il relativo script.

    Però, da ciò che chiedi nelle ultime domande, mi viene da pensare (scusami se sbaglio) che non ti sia ben chiaro il concetto di "elementi del DOM creati e disponibili per la manipolazione".

    Apro una parentesi; tu chiedi infatti:
    Se in una pagina gli elementi DOM sono già definiti nel codice HTML è meglio utilizzare l'anonymous self-invoking
    ma mi lascia perplesso l'uso della frase "sono già definiti nel codice HTML" come se tu stia dando per scontato che il semplice codice HTML, della pagina che si sta aprendo, sia sufficiente per determinare che gli elementi (relativi chiaramente a quel codice) siano disponibili e manipolabili; non è esattamente così - ma forse ho inteso male io ciò che hai indicato.

    Ancora, scrivi:
    gli elementi del DOM sono creati dinamicamente durante il caricamento
    ma in questo caso il termine "dinamicamente" mi pare contrasti con quello di "caricamento". In generale, durante il caricamento del documento (cioè della pagina HTML che si va ad aprire), gli elementi sono creati, per così dire, in modo "statico", cioè quelli vengono "letti" (durante il parsing) e quelli vengono creati; mentre con "elementi creati dinamicamente" in genere ci si riferisce a quegli elementi creati in modo "asincrono" cioè in momenti non determinati, dopo che il documento è già bello che caricato. In questo caso il ready stesso da solo non può assicurarti che gli elementi siano disponibili per la manipolazione - ma magari ho ancora inteso male io.

    Forse (correggimi se sbaglio) il tuo dubbio nasce proprio da un'errata concezione di queste nozioni.

    Cerco di chiarire velocemente. Il codice HTML è un semplice markup che viene dato in pasto al browser, ma il documento in sé non possiede alcun oggetto, funzione, metodo, o chissà ché - è semplicemente una "zuppa di tag".

    Quando si apre il documento HTML, quindi il browser riceve questa "zuppa", avvengono diversi passaggi (riassumo a grandi linee):

    - il browser legge questo codice; in questo punto non è stato ancora creato il DOM (modello a oggetti del documento) e nessun elemento è ancora disponibile, ne tanto meno gli script sono eseguiti;

    - avviene il parsing (cioè una interpretazione del codice) e quindi...

    - viene costruita la mappa DOM (albero strutturato degli oggetti)

    - infine vengono creati gli elementi leggendo il DOM nel verso in cui è stato creato (esattamente nel verso in cui viene letto e interpretato il codice HTML, dall'alto verso il basso)

    - in quest'ultimo passaggio tutti gli elementi (compresi gli script) vengono creati (leggendoli dall'alto verso il basso) e sono resi disponibili (e quindi manipolabili da script) man mano che ciascuno di essi è creato.

    Nota bene che anche gli elementi script vengono creati nello stesso modo di tutti gli altri elementi della pagina. Questi sono quindi eseguiti singolarmente, cioè ciascuno script (qualora sia frammentato in più parti nel documento) è letto, interpretato, ed eseguito nel momento in cui viene creato, prima di proseguire con la creazione degli elementi successivi.

    Va da sé quindi che gli elementi non sono disponibili tutti nel momento in cui è semplicemente letto il codice HTML, ma questi vengono resi disponibili durante il processo di parsing. Gli script, anch'essi letti ed eseguiti man mano durante questo processo, nel momento in cui sono eseguiti (che siano script fuori da funzioni oppure dentro a funzioni eseguite in quell'istante) possono quindi far riferimento solo esclusivamente agli elementi che li precedono, cioè a quegli elementi che vengono creati prima che lo script stesso sia eseguito.

    Per concludere: un semplice script posto alla fine del body, viene eseguito dopo la creazione di tutti gli elementi della pagina (dando per scontato che dopo il body stesso non sia presente nessun altro elemento). In tal caso tutti gli elementi, che sono manipolati da questo script, saranno certamente disponibili.

    Lo script presente in una IIFE (la tua self-invoking) sarà eseguito comunque all'istante in cui è letto, per cui, se questo fa diretto riferimento ad elementi del DOM, devi assicurarti che tali elementi siano disponibili.

    Il metodo ready di jQuery viene proposto proprio per risolvere questo problema, cioè per eseguire il codice anche se posto, ad esempio, nell'head della pagina HTML (cioè prima che il body e tutti gli elementi in esso presenti siano stati creati). E' simile all'evento load del body, per cui (a grandi linee), il callback con tutto lo script che gli sta dentro, viene eseguito solo dopo che la fase di parsing è terminata, con la certezza che tutti gli elementi (dell'HTML appena esaminato) sono disponibili sulla pagina e quindi manipolabili da script.

    Per rispondere alle tue domande, devi considerare i concetti appena accennati:

    - puoi eseguire qualsiasi script che faccia riferimento ad elementi del DOM (che sia fuori da funzioni o dentro IIFE) solo se questi sono stati già creati e disponibili per la manipolazione;

    - puoi usare una IIFE se ti serve mantenere un ambito locale per le variabili utilizzate nello script stesso, dal momento che si tratta comunque di una funzione;

    - puoi usare infatti una IIFE, passando l'oggetto principale jQuery come riferimento, per situazioni in cui possono presentarsi conflitti tra librerie;

    - puoi usare il metodo ready di jQuery in qualunque punto del documento, per avere certezza che lo script al suo interno sia eseguito solo dopo la creazione degli elementi DOM (relativi alla pagina appena aperta);

    - per situazioni di conflitto puoi inoltre usare il metodo ready ma col riferimento a jQuery che sarà passato come argomento del callback (vedi: Use the Argument That's Passed to the jQuery( document ).ready() Function)

    Ancora, se ti serve manipolare all'istante determinati elementi, può essere più "rapido" (in termini di esecuzione, rispetto al ready) inserire il tuo script (ovviamente tra <script></script>) subito dopo i tag relativi agli elementi da manipolare. E' evidente che lo script sarà eseguito subito senza attendere che il processo di parsing sia concluso, come invece avverrebbe per il ready.

    La scelta di una delle varie soluzioni andrà valutata a seconda di cosa ti serve ottenere nello specifico, avendo ovviamente chiari anche i concetti appena esposti.

    A mio parere non è comunque possibile determinare "meglio una o meglio l'altra" senza conoscere il contesto, le varie peculiarità e le tue esigenze.
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2019
    Messaggi
    41
    Ciao @KillerWorm ho una pagina ma non saprei se gli elementi sono già definiti nel DOM, ti incollo il codice e ti linko la pagina http://android0.altervista.org/Tris-js-original.html.

    codice:
    <!DOCTYPE html>
    <html dir="ltr">
    
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="user-scalable=no, shrink-to-fit=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
        <title>Tic-Tac-Toe Game written in Javascript</title>
        <style>
    body {
        background: #ffffff;
        font: normal 16px courier, arial;
        text-align: center;
    }
    
    .tic-tac-toe .scoreboard {
      margin: auto;
    }
    
    .tic-tac-toe .scoreboard .score {
        text-align: center;
        font-size: 80px
    }
    
    .tic-tac-toe .scoreboard .score.X {
        color: #238EE1;
    }
    
    .tic-tac-toe .scoreboard .score.O {
        color: #FF1010;
    }
    
    
    .tic-tac-toe .board table {
        cell-spacing: 0px;
        border-spacing: 0px;
        border-collapse: collapse;
        margin-top: 30px;
        margin-bottom: 30px;
        margin: 30px auto;
    }
    
    .tic-tac-toe .board td {
        border: 4px solid #000;
        height: 100px;
        width: 100px;
        text-align: center;
        font: 200 60px helvetica neue, arial;
        cursor: pointer;
        -webkit-touch-callout: none;
        -webkit-user-select: none;
        -khtml-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
    }
    
    .tic-tac-toe .board tr:first-child td {
        border-top: none
    }
    
    .tic-tac-toe .board tr:last-child td {
        border-bottom: none
    }
    
    .tic-tac-toe .board tr td:first-child {
        border-left: none;
    }
    
    .tic-tac-toe .board tr td:last-child {
        border-right: none;
    }
    
    .tic-tac-toe .board td.X {
        color: #238EE1;
    }
    
    .tic-tac-toe .board td.O {
        color: #FF1010;
    }
    </style>
    <script src="https://code.jquery.com/jquery-1.0.js"></script>
    </head>
    
    <body dir="ltr" style="background:#ffffff;">
    
        <h1 class="title"> Tic-Tac-Toe scritto in Javascript </h1>
    
        <div class="game-panel">
    
            <div class="tic-tac-toe">
                <table class="scoreboard">
                    <tbody><tr>
                        <td> Giocatore 1 </td>
                        <td width="30"> &nbsp; </td>
                        <td> Giocatore 2 </td>
                    </tr>
                    <tr>
                        <td class="score X">0</td>
                        <td> &nbsp; </td>
                        <td class="score O">0</td>
                    </tr>
                </tbody></table>
    
                <div class="board"><table><tbody><tr><td row="0" column="0"></td><td row="0" column="1"></td><td row="0" column="2"></td></tr><tr><td row="1" column="0"></td><td row="1" column="1"></td><td row="1" column="2"></td></tr><tr><td row="2" column="0"></td><td row="2" column="1"></td><td row="2" column="2"></td></tr></tbody></table></div>
    
                <button class="btn-reset"> Reset </button>
    
                <select class="grid-options">
                    <option value="2"> 2 X 2 </option>
                    <option value="3" selected=""> 3 X 3 </option>
                    <option value="4"> 4 X 4 </option>
                    <option value="5"> 5 X 5 </option>
                    <option value="6"> 6 X 6 </option>
                </select>
            </div>
    
        </div>
    
        <script>
    function TicTacToe(selector) {
    
        var main_element = $(selector)[0],
            score_X = $('.score.X')[0],
            score_O = $('.score.O')[0],
            board = $('.board')[0],
            grid_options = $('.grid-options')[0],
            reset_btn = $('.btn-reset')[0];
    
        var grid_size = 3,
            moves = 0,
            scores = {
                X: 0,
                O: 0
            },
            data = {};
    
        $('.grid-options').change(function(e) {
          grid_size = $(this).val();
          init();
        });
    
        init();
        
        $('.btn-reset').click(function(e) {
          reset_btn = init();
        });
    
        function paint() {
            var table = '<table>';
            for (var i = 0; i < grid_size; i++) {
                table += '<tr>';
                for (var j = 0; j < grid_size; j++) {
                    table += '<td row="' + i + '" column="' + j + '"></td>';
                }
                table += "</tr>";
            }
            $(board).html(table);
    
            var columns = $('td');
            for (i = 0; i < columns.length; i++) {
                $(columns[i]).click(function(e) {
                td = mark(e);
                })
            }
    
        }
    
        function mark(e) {
    
            var evt = e || event;
            var td = evt.target || evt.srcElement;
    
            if ($(td).html()) {
                return;
            }
    
            var row = $(td).attr('row'),
                column = $(td).attr('column');
    
            var current_mark = moves % 2 === 0
                ? 'X'
                : 'O';
    
            $(td).html(current_mark);
            $(td).addClass(current_mark);
            data[row + '' + column] = current_mark;
    
            moves++;
    
            (function($) {
                if (didWin(current_mark)) {
                    alert(current_mark + ' vince la partita!');
                    scores[current_mark]++;
                    updateScoreboard();
                    empty();
                } else if (moves === Math.pow(grid_size, 2)) {
                    alert("Pareggio!");
                    empty();
                }
            })(jQuery);
    
        }
    
        function didWin(mark) {
    
            var vertical_count = 0,
                horizontal_count = 0,
                right_to_left_count = 0,
                left_to_right_count = 0;
    
            for (var i = 0; i < grid_size; i++) {
    
                vertical_count = 0;
                horizontal_count = 0;
    
                for (var j = 0; j < grid_size; j++) {
    
                    if (data[i + '' + j] == mark) {
                        horizontal_count++;
                    }
    
                    if (data[j + '' + i] == mark) {
                        vertical_count++;
                    }
    
                }
    
                if (data[i + '' + i] == mark) {
                    left_to_right_count++;
                }
    
                if (data[(grid_size - 1 - i) + '' + i] == mark) {
                    right_to_left_count++;
                }
    
                if (horizontal_count == grid_size || vertical_count == grid_size) {
                    return true;
                }
    
            }
    
            if (left_to_right_count == grid_size || right_to_left_count == grid_size) {
                return true;
            }
    
            return false;
        }
    
        function empty() {
            moves = 0;
            paint();
            data = {};
        }
    
        function init() {
            empty();
            scores = {
                X: 0,
                O: 0
            };
            updateScoreboard();
        }
    
        function updateScoreboard() {
            $('.score.X').html(scores.X);
            $('.score.O').html(scores.O);
        }
    
    }</script>
        <script>
            TicTacToe('.game-panel');
        </script>
    
    </body>
    
    </html>
    Nella pagina ho utilizzato una funzione anonima self-invoking (IIFE) e non saprei se gli elementi sono già definiti nel DOM. Grazie per la cordialità e disponibilità.

  4. #4
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    ho una pagina ma non saprei se gli elementi sono già definiti nel DOM
    Perdonami ma non capisco la tua perplessità. Se leggi con attenzione tutte le indicazioni nel mio precedente post, dovresti riuscire a comprendere da te se in quel punto sono definiti già gli elementi del DOM e come impostare la cosa.

    A me pare non ci sia bisogno di alcuna funzione in quel punto, né di IIFE né di ready, ma potrei sbagliarmi. Puoi farmi capire perché tu lo ritenga necessario?
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2019
    Messaggi
    41
    @KillerWorm perchè avevo un dubbio perchè non riuscivo a capire se gli elementi DOM erano già definiti ma guardando attentamente sia il codice che il caricamento della pagina gli elementi sono già definiti.

    codice:
    (function($) {
                if (didWin(current_mark)) {
                    alert(current_mark + ' vince la partita!');
                    scores[current_mark]++;
                    updateScoreboard();
                    empty();
                } else if (moves === Math.pow(grid_size, 2)) {
                    alert("Pareggio!");
                    empty();
                }
            })(jQuery);
    Ho utilizzato questa funzione e mi era venuto un dubbio ma ho notato che gli altri elementi sono caricati prima dell'esecuzione di questa funzione. Grazie per la delucidazione.

  6. #6
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    ma ho notato che gli altri elementi sono caricati prima dell'esecuzione di questa funzione
    Esatto tutti gli elementi del DOM mi pare vengano creati prima che sia eseguito quello script. Quindi non serve nessun ready in questo caso ma non serve nemmeno quella IIFE a mio parere.

    Anche se non da problemi, non ha alcun senso usarla; e non ha nemmeno senso passare il riferimento a jQuery perché, come ti ho indicato sopra, questa tecnica viene usata solitamente quando ci sono conflitti di librerie, in modo tale che la variabile $, quando usata localmente dentro la funzione, faccia esattamente riferimento a jQuery e non ad altre eventuali librerie definite invece a livello globale.

    Nel tuo caso però non vedo altre librerie che possano creare conflitti, né tanto meno la variabile $ viene usata dentro quella funzione. Mi chiedo quindi perché tu abbia pensato di usare una cosa simile; non ce ne motivo in questo caso, tant'è che potresti eseguire quella porzione di script direttamente, senza bisogno di racchiuderla dentro alcuna funzione.
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

  7. #7
    Utente di HTML.it
    Registrato dal
    Mar 2019
    Messaggi
    41
    Ciao @KillerWorm scusa se ti rispondo adesso, ho provato il tuo consiglio e funziona. Ho rimosso la funzione dentro quella parte di codice e l'ho lasciata nello script. Grazie per la cordialità.

  8. #8
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    Nessun problema mi fa piacere che funzioni, buon proseguimento.
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

Tag per questa discussione

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.