Domande sulla sintassi corretta jQuery

PazzoFrontEnd

Utente Attivo
8 Ott 2013
46
0
6
Buongiorno a tutti,
avrei alcune domande sulla sintassi del codice che non riesco ancora a comprendere appieno. Le mie sono domande per capire pezzi di codice trovati qui e li su un sito che sto rifacendo e pertanto sono più che altro "didattiche". Vado per punti:

1) Ho trovato questo pezzo di codice:
Codice:
$(window).ready(function(){...});
Io sapevo che si potesse usare il solito "$(document).ready()" o alternativamente il "$(window).load()", mi sembra che il codice postato non esista, è giusto?

2) Ho un costrutto del genere:

Codice:
(function() {

    var mySelector = $('.myClass');
    if (mySelector.length < 1) return;

})();
Chi sa spiegarmi perchè c'è solo il "return" senza nulla, dopo la condizione? Cosa "ritorna" la funzione in tal caso? E poi sempre in relazione a questo pezzo di codice, altra domanda: perchè la funzione è incapsulata tutta dentro le parentesi "(...)". In altre parole che differenza c'è tra lo scrivere:
Codice:
  function myFunction() {
         var mySelector = $('.myClass');
         if (mySelector.length < 1) return;
  }
e quella postata poco sopra racchiusa tra "(function(){...})();"

3) infine terzo pezzo di codice:
Codice:
 mySelector.find(".myClass a").on("click", function(e, _u, $el) {
    return true;
    /* funzione disabilitata togliere il return true per riattivarla */
    $el = $(this);
    if ($el.parent().hasClass("otherClass")) return true;
    e.preventDefault();
    try {
        _u = $el.parent().attr("rel");
        if (typeof _u == "undefined" || _u == "") return;
        $el.hide();
    } catch (error) {
        console.log(error);
    }
});
Il commento " /* funzione disabilitata togliere il return true per riattivarla */" a quale return true si riferisce? al primo o al secondo? E perchè con return true è disabilitata la funzione che parte al trigger del click?

Per il momento è tutto :) Spero possiate darmi una mano, sono un pò confuso, Vi ringrazio anticipatamente.
Buona giornata a tutti
 

WmbertSea

Utente Attivo
28 Nov 2014
178
27
28
Ciao, rispondo ai vari punti:
1) Ho trovato questo pezzo di codice:
Codice:
$(window).ready(function(){...});
Io sapevo che si potesse usare il solito "$(document).ready()" o alternativamente il "$(window).load()", mi sembra che il codice postato non esista, è giusto?
Come tu hai giustamente indicato, la sintassi corretta è
Codice:
$(document).ready(function(){...});
o altre sintassi equivalenti:
Codice:
jQuery(document).ready(function($){...});
Codice:
$(function(){...})
o ancora altre sintassi analoghe anche se sconsigliate:
Codice:
$(document).on("ready",function(){...})
Codice:
$().ready(function(){...})
In tutti questi casi la funzione di callback viene richiamata appena il DOM è stato inizializzato, cioè tutti gli elementi sulla pagina sono disponibili per la manipolazione.

La differenza sostanziale con $(window).load(function(){...}) è che, in quest'ultimo, il callback viene richiamato quando, oltre ad essere stato inizializzato il DOM, anche tutte le immagini presenti sulla pagina sono state caricate completamente.

Il codice che hai trovato è un mix tra la sintassi dei due metodi. Questo non ha molto senso, quindi presumo sia stato scritto in quel modo per errore.
Ma anche se non ha senso, quello script funzionerà comunque perché il selettore viene semplicemente ignorato.

Sulla documentazione è scritto che il metodo ready() può essere chiamato solo su un oggetto jQuery corrispondente al documento corrente, quindi il selettore può essere omesso.

In effetti è possibile specificare qualsiasi cosa per il selettore, il metodo ready() farà comunque riferimento direttamente al document, ignorando di fatto l'oggetto restituito dal selettore.

A dimostrazione, con ognuna di queste forme si ottiene lo stesso risultato:
Codice:
$(document).ready(function(){...});
$(window).ready(function(){...});
$("pippo").ready(function(){...});
$(null).ready(function(){...});
$(true).ready(function(){...});
$({}).ready(function(){...});
$().ready(function(){...});
Chiaramente, il fatto che funzioni, non significa che sia comunque una forma corretta.
[HR][/HR]
2) Ho un costrutto del genere:

Codice:
(function() {

    var mySelector = $('.myClass');
    if (mySelector.length < 1) return;

})();
Chi sa spiegarmi perchè c'è solo il "return" senza nulla, dopo la condizione? Cosa "ritorna" la funzione in tal caso?
In questo caso la funzione non restituisce praticamente niente. Il return viene usato in quel modo per uscire dalla funzione interrompendo quindi l'esecuzione dello script che segue quella riga fino alla fine della funzione.
Nello script che hai postato non avrebbe alcun senso perché non c'è alcuno script dopo quella riga, ma presumo che ci sia stato dell'altro script che verrebbe quindi eseguito nel caso in cui non venisse verificata quella condizione.
Chiaramente l'esecuzione dello script prosegue dal punto che segue l'istruzione da cui è stata chiamata quella stessa funzione.
Il funzionamento è simile all'istruzione break utilizzata per interrompere l'esecuzione di un ciclo.
[HR][/HR]
perchè la funzione è incapsulata tutta dentro le parentesi "(...)". In altre parole che differenza c'è tra lo scrivere:
Codice:
  function myFunction() {
         var mySelector = $('.myClass');
         if (mySelector.length < 1) return;
  }
e quella postata poco sopra racchiusa tra "(function(){...})();"
Si tratta di una tecnica chiamata "immediately-invoked function expression" (o altri termini simili come "self-invoking function", "self-executing anonymous function", ecc.), cioè una funzione (per meglio specificare, un'espressione di funzione) che si auto-esegue.
Di fatto è una funzione anonima (o anche nominale) racchiusa tra parentesi che richiama se stessa così come si fa quando si richiama una semplice funzione, cioè apponendo le parentesi dove è possibile passare anche eventuali argomenti.
Questa tecnica è usata per vari motivi, generalmente per definire, in modo distinto, particolari scope (ambiti di validità delle variabili).
[HR][/HR]
3) infine terzo pezzo di codice:
Codice:
 mySelector.find(".myClass a").on("click", function(e, _u, $el) {
    return true;
    /* funzione disabilitata togliere il return true per riattivarla */
    $el = $(this);
    if ($el.parent().hasClass("otherClass")) return true;
    e.preventDefault();
    try {
        _u = $el.parent().attr("rel");
        if (typeof _u == "undefined" || _u == "") return;
        $el.hide();
    } catch (error) {
        console.log(error);
    }
});
Il commento " /* funzione disabilitata togliere il return true per riattivarla */" a quale return true si riferisce? al primo o al secondo? E perchè con return true è disabilitata la funzione che parte al trigger del click?
Si riferisce presumibilmente al primo. Infatti quel return iniziale farà uscire subito dalla funzione, come spiegato al punto 2. Quindi lo script che segue quella riga non sarà eseguito (in questo senso, la funzione è disabilitata). Che ci sia true o niente o qualsiasi altra cosa, credo sia irrilevante.
[HR][/HR]
Spero di avere schiarito la confusione.
Buon proseguimento.
 

PazzoFrontEnd

Utente Attivo
8 Ott 2013
46
0
6
Ciao WmbertSea
innanzitutto grazie mille, sei stato esaustivissimo e precisissimo. Se mi è permesso, posso chiederti ulteriori delucidazioni dopo gli spunti che mi hai postato?

1) Prima domanda: quando scrivi questo:

Codice:
jQuery(document).ready(function($){...});
Nella pratica cosa cambia da "$(document).ready(function(){...})". Perchè passare come parametro il "$" invece che utilizzare una function anonima?

2) Per il secondo punto, quindi, mi sembra di capire che una funzione "che invoca se stessa" non c'è bisogno di richiamarla ma effettuerà sempre il suo codice o sbaglio? In pratica:

Codice:
(function() {

 alert("ciao")

})();

//equivale a scrivere:

 function myFunction() {
        alert("ciao");
  }

myFunction();
Giusto??

Inoltre potresti farmi un esempio pratico quando dici "Questa tecnica è usata per vari motivi, generalmente per definire, in modo distinto, particolari scope (ambiti di validità delle variabili)...". ?


3) nel terzo pezzo di codice che ho inserito, mi confermi che scrivere "return true;" sarebbe, eventualmente, equivalente allo scrivere "return false;" per uscire dalla funzione? O c'è qualche controindicazione?

Grazie e buon weekend pasquale
 

Salvatore HeadWolf

Utente Attivo
19 Feb 2013
20
1
3
trovalost.it
Ciao PazzoFrontEnd,

provo a risponderti brevemente.

[...]
Codice:
$(window).ready(function(){...});
In jQuery ci sono 3 alternative equivalenti a quello che scrivi (fonte):

Codice:
    $( document ).ready( handler )
    $().ready( handler )
    $( handler )
quindi dovrebbe essere chiaro che è sempre la stessa cosa.

2) Ho un costrutto del genere:

Codice:
(function() {

    var mySelector = $('.myClass');
    if (mySelector.length < 1) return;

})();
Chi sa spiegarmi perchè c'è solo il "return" senza nulla, dopo la condizione?
il return serve semplicemente a spezzare la condizione, cioè impedisce al codice di eseguire oltre se, nello specifico, myselector è lungo 0 - è una condizione safe, perchè potresti avere un errore diversamente.

3)
Codice:
 mySelector.find(".myClass a").on("click", function(e, _u, $el) {
    return true;
    /* funzione disabilitata togliere il return true per riattivarla */
    $el = $(this);
    if ($el.parent().hasClass("otherClass")) return true;
    e.preventDefault();
    try {
        _u = $el.parent().attr("rel");
        if (typeof _u == "undefined" || _u == "") return;
        $el.hide();
    } catch (error) {
        console.log(error);
    }
});
il return true a cui si riferisce il commento è il primo.

anche qui, anticipa il ritorno della funzione impedendogli di andare avanti, tutto qui: per attivare la funzione commenta con doppio slash // e la funzione si attiverà :)

Spero sia tutto chiaro :)
 

WmbertSea

Utente Attivo
28 Nov 2014
178
27
28
Ciao
Perchè passare come parametro il "$" invece che utilizzare una function anonima?
Per chiarezza, si tratta comunque di una funzione anonima. In questo caso la differenza sta solo nel passaggio di quel parametro.
Perché viene passato quel parametro o perché generalmente viene trovata quella forma col parametro specificato? Cerco di spiegare.
La forma jQuery(document).ready(function($){...}); viene usata solitamente quando si hanno dei conflitti con altre librerie JavaScript che, come jQuery, utilizzano $ come funzione base o nome variabile che ne definisce l'oggetto principale.

Facciamo un passo indietro.
Quando includiamo la libreria jQuery sulla nostra pagina, la variabile $ è un alias della variabile jQuery definita nel global scope (l'ambito di validità principale del documento).
L'oggetto principale, di nome jQuery, è genericamente utilizzato tramite il suo alias, il carattere $, per mantenere uniformità con la libreria Prototype.
Fonte: http://it.wikipedia.org/wiki/JQuery

Per cui queste due forme (senza parametro) sono totalmente equivalenti:
Codice:
jQuery(document).ready(function(){...});
$(document).ready(function(){...});
Ora esaminiamo il caso in cui ci sia una situazione di conflitto tra librerie.
Ad esempio, sulla stessa pagina si utilizzano le due librerie jQuery e Prototype.
Per entrambe viene utilizzato il carattere $ per definirne l'oggetto o la funzione di base.
Questa variabile è definita, come già detto, nel global scope. Chiaramente quando si vanno ad includere le due librerie si crea un conflitto, non potremmo usare $ per entrambe.

Per risolvere, in linea di massima è possibile usare la variabile jQuery anziché $ (che invece farà riferimento alla funzione della libreria Prototype).
Per tale motivo usiamo la forma jQuery(document).ready(function(){...});

Ma anche con tutto il resto del codice dovremo fare attenzione ad usare JQuery al posto di $ nelle chiamate di JQuery.
Non è il massimo nella maggior parte dei casi. Pensiamo ad esempio a dei plugin o degli script di terze parti che vogliamo inserire nel nostro documento. Tutti i riferimenti, in jQuery, a $ andrebbero convertiti con jQuery. E' una bella seccatura.

Possiamo però ovviare il problema passando, appunto, il riferimento dell'oggetto jQuery globale, attraverso una variabile definita come argomento della funzione su ready().
Infatti, l'argomento di tale funzione, farà riferimento all'oggetto globale jQuery.
La variabile $ è definita a livello locale (quindi nello scope della funzione) e sarà praticamente un alias dell'oggetto jQuery.
Per cui, all'interno della funzione, potremmo continuare ad usare tranquillamente $ anziché jQuery, senza avere conflitti.

Per questo motivo la forma jQuery(document).ready(function($){...}); viene generalmente indicata con la specificazione della variabile $ come argomento della funzione.

Per ulteriori informazioni sui conflitti tra librerie, ti consiglio di fare qualche ricerca in riferimento a jQuery.noConflict()[HR][/HR]
2) Per il secondo punto, quindi, mi sembra di capire che una funzione "che invoca se stessa" non c'è bisogno di richiamarla ma effettuerà sempre il suo codice o sbaglio? In pratica:

Codice:

(function() {

alert("ciao")

})();

//equivale a scrivere:

function myFunction() {
alert("ciao");
}

myFunction();

Giusto??
In questo caso il risultato è lo stesso.
La differenza sostanziale è che, nella prima forma, la funzione anonima viene eseguita una volta e poi muore lì senza restare immagazzinata in memoria.

Inoltre potresti farmi un esempio pratico quando dici "Questa tecnica è usata per vari motivi, generalmente per definire, in modo distinto, particolari scope (ambiti di validità delle variabili)...". ?
Per capire, può andare bene anche l'esempio che hai postato tu:
Codice:
(function() {
    var mySelector = $('.myClass');
    if (mySelector.length < 1) return;
})();
In questo caso quella variabile mySelector ha validità solo dentro la funzione, non può essere raggiunta dall'esterno della funzione stessa, come è normale che sia perché si tratta pur sempre di una funzione.

Per cui quel pezzettino di script serve semplicemente a creare uno scope locale momentaneo (diciamo così) dove usare quella determinata variabile. Non c'è molto da capire in questo caso.
Ad ogni modo, se ritieni necessario approfondire, ti consiglio di consultare qualche guida per capire meglio il significato di "scope":
http://it.wikipedia.org/wiki/Visibilità_(programmazione)

Un uso più intensivo delle funzioni auto eseguite si può trovare nei "module pattern" e nelle "closure". Non credo però sia il caso di approfondire l'argomento su tali concetti in questa discussione. Se tu sei interessato, ti invito piuttosto a fare delle ricerche online partendo magari dai termini che ti ho indicato.
[HR][/HR]
3) nel terzo pezzo di codice che ho inserito, mi confermi che scrivere "return true;" sarebbe, eventualmente, equivalente allo scrivere "return false;" per uscire dalla funzione? O c'è qualche controindicazione?
No, mi correggo. Se metti return false, in pratica stai interrompendo l'effetto di default dell'evento click (lo stesso che utilizzare e.preventDefault()), oltre ad interrompere l'esecuzione dello script che viene dopo.
 

PazzoFrontEnd

Utente Attivo
8 Ott 2013
46
0
6
Ciao

Scusa per il ritardo ma con le feste di mezzo ho avuto poco tempo per venire sul forum. Torno a ringraziarti per le tue risposte molto esaustive. In questi giorni ho un po "studiato" e mi sono imbattuto su internet in una self-invoce function NON anonima, del tipo:

Codice:
(function foo() {
    //some code
})();
Mi sapresti dire che differenza c'è tra una self-invoke function anonima ed una non anonima? Anche in virtù delle tue parole di prima:
La differenza sostanziale è che, nella prima forma, la funzione anonima viene eseguita una volta e poi muore lì senza restare immagazzinata in memoria.
Se quest'ultima muore al di fuori delle parentesi, perchè darle un nome se non può essere richiamata con "foo()" in qualche altra parte del codice?

Infine ( scusa se approfitto :) )a: mi sai dare qualche dritta sul nesso che c'è tra javascript e programmazione ad oggetti? Come è possibile (se è possibile o se solo in minima parte) replicarla con questo linguaggio di scripting?

Grazie e buonanotte
 
Ultima modifica:

WmbertSea

Utente Attivo
28 Nov 2014
178
27
28
No problem, "buone fatte feste!".

Una "funzione nominale auto eseguibile" può essere richiamata dal suo stesso interno. Infatti tale funzione risulta definita nell'ambito di visibilità locale della funzione stessa.

Giusto per verificare:
Codice:
(function foo() {
  console.log(foo); // function foo()
})();
console.log(foo); // errore: 'foo' non è definito
In particolare, si dice "ricorsione" quella tecnica per cui una funzione chiama se stessa. La ricorsione è usata in vari contesti di programmazione per eseguire particolari operazioni (l'esempio più banale è il calcolo di un numero fattoriale).

Riguardo JavaScript e la programmazione ad oggetti, non ho inteso cosa vorresti sapere di preciso. Però mi pare di capire che si vada a finire in un argomento di carattere troppo generale, abbastanza dispersivo per discuterne qui, peraltro fuori tema rispetto l'oggetto di questa discussione, e che potrebbe far nascere sterili dibattiti perché ci sono diverse scuole di pensiero a riguardo.

Mi limito a dire, da quel che so, che JavaScript può essere definito come un linguaggio di programmazione orientato agli oggetti (OOP, che dir si voglia) perché possiede quelle prerogative da poterlo definire tale, anche se esistono varie differenze rispetto ad altri linguaggi propriamente OOP.

Se ti serve sapere qualcosa di più particolare sarebbe opportuno aprire una nuova discussione relativa all'argomento. Ad ogni modo ti invito ad effettuare prima delle ricerche online (c'è molto materiale su cui documentarsi su tale argomento).

Buonanotte!
 

WmbertSea

Utente Attivo
28 Nov 2014
178
27
28
Non c'è di che, mi fa piacere essere stato d'aiuto.
A presto, buonanotte.