Newsgroup: it.comp.lang.javascript
Titolo: funzioni annidate in funzione anonima

Sono in un vicolo cieco nel tentativo di eseguire una funzione annidata 
dentro una funzione anonima.
Ho questo codice:
 
var func=function(){
...
   function nestedFunc(){
   ...
   }
...
}
 
func();
 
A un elemento della pagina vorrei associare la funzione nestedFunc.
 
Se scrivo nestedFunc() ottengo "is not defined" (e fin qui ci arrivo).
Se invece scrivo func.nestedFunc() ottengo "is not a function".
 
Come si richiama correttamente nestedFunc?
 
 

 Se invece scrivo func.nestedFunc() ottengo "is not a function".
 
provato senza le parentesi?

 provato senza le parentesi?
 
Provato ora. La console di Firebug non mi mostra nessun errore, ma non 
succede niente (cioè la funzione non viene eseguita).

 Come si richiama correttamente nestedFunc?
 
Come ho detto, non lo fai. Devi rendere `nestedFunc` o non nested, che
magari non ve ne ï¿œ la necessitï¿œ (c'ï¿œ? Come mai?), oppure creare una closure.
Creando una closure, tu rendi `nestedFunc` accessibile da un'altro scope
che non sia quello locale della funzione, ma cosï¿œ facendo non distruggi
mai lo scope locale, anche se l'esecuzione della funzione ï¿œ terminata.
Uno zombie.
 
Le closure sono uno strumento potentissimo di JS, ma se non si conoscono
o si usano a sproposito fanno solo casino. Esempi di come puoi rendere
disponibile `nestedFunc`:
 
 
    var func = function func() {
        // do something
 
        return function nestedFunc() {
            // do something else in the local scope
        }
    }
 
    var nestedFunc = func();
 
    nestedFunc();
 
Oppure, tipo come volevi fare tu:
 
    var func = function func() {
        // do something
 
        func.nestedFunc = function() {
            // do something else in the local scope
        }
    }
 
    // Attento, `nestedFunc` esiste solo se `func` ï¿œ stata eseguita,
    // dato che da essa ï¿œ creata
    alert(typeof func.nestedFunc === "undefined") // true
 
    func();
 
    alert(typeof func.nestedFunc === "function") // true
 
    func.nestedFunc();
 
    // Attento, per la stessa ragione ogni volta che chiami `func`
    // crei una nuova `nestedFunc`!
 
    var oldNested = func.nestedFunc;
 
    alert(oldNested === func.nestedFunc); // true
 
    func();
 
    alert(oldNested === func.nestedFunc); // false
 
Oppure, generalizzando, esportando `nestedFunc` in un qualche oggetto:
 
    var func = function(exports) {
        // do something
 
        exports.nestedFunc = function() {
            // do something else in the local scope
        }
    }
 
    alert(typeof nestedFunc === "undefined");
    func(window);
    alert(typeof nestedFunc === "function");
 
Questo ï¿œ un approccio simile a ciï¿œ che viene usato per scrivere moduli
compatibili a commonjs / nodejs.


Ovvio, se anche tu avessi un riferimento a funzione, senza parentesi,
non la eseguiresti. A meno che non sia un getter, ovviamente.
 
Così stai cercando di avere il valore di una fantomantica proprietà di
`func` chiamata `nestedFunc` che non esiste, niente viene mostrato su
Firebug perché non fai il dump del valore:
 
    console.log(func.nestedFunc === undefined) // true

      // crei una nuova `nestedFunc`!
 
Non sarebbe un problema, devo eseguire func una volta sola, ma 
nestedFunc diverse volte. Ho inteso bene?

> Oppure, tipo come volevi fare tu:
 
Cosa ne pensate di questo:
http://stackoverflow.com/questions/4277378/how-do-i-call-a-nested-function-in-a-parent-document-from-an-iframe
 
 
"Is there a more elegant way of doing this?"

 nestedFunc diverse volte. Ho inteso bene?
 
Onestamente a vedere quello che hai scritto ora, mi sa che no, non hai
inteso bene. Hai preso l'unico esempio che ti avevo fatto per fare un
parallelo con il tuo, ma che NON dovevi prendere come esempio :) Non si
usa normalmente, ï¿œ sbagliato. Rimuovilo, fai finta che non l'abbia mai
scritto (anche perchï¿œ se la funzione ï¿œ veramente anonima, ï¿œ una cosa che
non puoi fare); e focalizzati sugli altri due.
 
Spero comunque che con questo post ti siano un po' piï¿œ chiare le idee.

 "Is there a more elegant way of doing this?"
 
Apriti cielo. Se proprio vogliono fare qualcosa del genere, perchï¿œ usare
una funzione? Basta un oggetto:
 
    var outer = (function() {
        function inner() {
            alert("hello");
        }
 
        return {inner : inner};
    })();
 
    parent.outer.inner(); // "hello"

 perché si usa tale approccio proprio per evitarlo. Non so se mi spiego.
 
Ti sei spiegato. Ora provo a spiegarmi io, nella speranza di riuscirci.
Il mio codice è composto da istruzioni e funzioni, più o meno così:
 
blocco istruzioni
funzione {}
funzione {}
funzione {}
blocco istruzioni
 
Il nocciolo è questo: i miei blocchi di istruzioni mi servono per creare 
nella pagina alcuni elementi (div, a) che richiamano tramite clic una 
funzione (in verità si tratta di più di una) del mio codice.
Se racchiudo tutto dentro una funzione anonima, ottengo l'errore che mi 
ha portato a iniziare questa discussione, perché l'elemento sul quale 
viene eseguito il clic richiama una funzione che non viene vista.
D'altronde, come tu mi hai spiegato, se creo una closure "sporco" il 
codice della pagina ospitante, cioè gli aggiungo gli/le 
oggetti/variabili dei due blocchi di istruzioni (se ho ben capito il 
punto), proprio come se lasciassi il codice così com'è (sempre se ho 
capito bene).
Nella mia situazione, cosa mi conviene fare? Lascio tutto così, o 
riscrivo in qualche modo?
Ho scritto questo a una prima lettura della tua risposta, il resto ho 
bisogno di rileggermelo probabilmente anche più volte perché la prima 
volta non c'ho capito nulla (scusa la confessione). Quindi ora ci dedico 
un po' di tempo.

      }(this)
 
Anche qui perdona la mia ignoranza: non ho mai visto scrivere (global) e 
(this). Li hai usati per eccesso di zelo, o altro?

 prima, chiamando in modo diverso la funzione interna?
 
Lascia perde questa domanda proprio idiota, me lo spieghi più sotto, sto 
rileggendo ora.

 prendi il primo che ti ho fatto:
 
Per me il resto ï¿œ roba tosta. Grazie mille del tempo che mi hai 
dedicato. Io ho bisogno di dedicarne almeno tre volte tanto per 
rileggere ancora e capire. Chiederï¿œ spiegazioni solo dopo avere 
insistito ancora da solo nella comprensione del testo.

 un po' di tempo.
 
Tranquillo, se c'ï¿œ qualcosa in cui sono stato poco chiaro dimmelo e
cercherï¿œ di spiegarmi meglio. Le closure, a volte possono risultare un
po' ostiche a chi proviene da un linguaggio canonico, ma una volta che
capisci il nocciolo ti sembrerï¿œ tutto semplicissimo.

 (this). Li hai usati per eccesso di zelo, o altro?
 
No, il punto è non c'è un modo "safe" per ottenere l'oggetto globale. Se
vuoi esportare qualcosa nello scope globale, devi far girare lo script
nello scope globale e passare `this`. Non posso usare `this`
internamente, perché "potrebbe" riferirsi ad altro. Quindi, per essere
sicuro, lo passo come prima cosa, che so che essendo tale funzione
eseguita come bookmarklet o nel global scope, `this` si riferisce
all'oggetto globale.
 
Probabilmente non lo hai mai visto, perché vedi script perlopiù scritti
solo per i browser. Nel browser, il global object è sempre `window`.
Quindi nella maggior parte dei casi non importa passarlo, dato che
`window` ha un riferimento a sé stesso (`window`) puoi sempre usare quello:
 
    !function() {
        // export to global object
        window.nested = function nested() {}
    }();
 
Ma JS non è più solamente usato all'interno dei browser. Quindi molti
script o moduli, non possono far affidamento al DOM o agli oggetti host
che il browser mette a disposizione a JavaScript - come window. Ergo
devi creare qualcosa di general purpose. Come i codice di cui sopra.
 
Nel caso in cui quel codice giri su un browser, `this` sarà equivalente
a window. Se gira su una shell JS (nodejs o altro), `this` sarà
equivalente all'oggetto globale di quell'ambiente.
 

 insistito ancora da solo nella comprensione del testo.
 
Di niente figurati. Se vuoi un po' di documentazione in merito, ci sono
diversi link che parlano dell'argomento (o puoi tranquillamente cercare
su google), io qui ho cercato di semplificarti un po' le cose (che tu ci
creda o no ;) ).

 si dice mai. Ma a parte questo, nient'altro.
 
??? Ma all'uscita della pagina non viene cancellato tutto?

 ??? Ma all'uscita della pagina non viene cancellato tutto?
 
Per questo si chiamano memory leak. :) Diciamo che solitamente puoi
averli più quando rimani nella pagina, e fai casini col DOM. Ma,
ovviamente per via di bug nei browser, possono rimanere anche fintanto
che il browser rimane aperto. Più o meno tutte le librerie che ho avuto
modo di vedere, in qualche browser in certi contesti, fanno un hook di
`onbeforeunload` e/o `onunload` per essere sicuri che il gc (garbage
collector) faccia il suo lavoro.

 per amor di semplicità.
 
In FF 3.6 l'ho provata e non funziona. Mi ricordo di avere cercato su 
web e avere trovato tanti altri che se ne lamentavano. In FF 7.0.1 non 
ho provato perché Firebug non funziona, e non saprei cos'altro adoperare.

 tutti i Firefox lo supportano correttamente.
 
C'hai ragione (so che non hai bisogno di sentirtelo dire, ma io ho 
bisogno di dirlo).
Ho completamente frainteso la questione confondendo .onclick con .click 
(che c'è in IE ma manca in FF).

      }(this)
 
Esempio modificato alla bisogna:
 
!function(global){
     var a = 2;
 
     var b = a * a;
 
     global.nested = function nested(c){
         var myvar = 0;
 
         myvar++;
         a++;
 
         console.log(a, b, myvar);
     }
 
     var a1 = document.body.appendChild(
     document.createElement("a")
     );
 
     a1.innerHTML ="hello";
     a1.href="javascript:nested()";
 
}(this)
 
Perché il click sul link mi restituisce "nested is not defined"?
C'è un modo per rendere disponibile nested() a link del tipo 
"javascript:..."?

 "javascript:..."?
 
In alternativa ho trovato che posso definire la proprietà .onclick.
Nel mio caso ho la complicazione che avrei a che fare con una funzione 
parametrica, ma ho visto che posso definire 
.onclick=function(){miafunzione(par1,par2,par3)}.
Mi rimane del tutto oscura la ragione del mancato funzionamento dei link 
del tipo javascript:. Io avrei preferito questo approccio, perché mi 
tranquillizza vedere sulla barra di stato il codice javascript da 
eseguire, però, se non si può...

 mio esempio con `exports` e `global`) è irrilevante.
 
Ok, mi sembra di esserci.
Alla fine ho puntato sulla seconda alternativa (solo un oggetto che 
"sporca" lo scope superiore) perché l'uso del return mi sarebbe 
risultato più ostico.
A prima vista non avrei detto che la differenza è irrilevante (perché 
immaginavo che il "motore" dovesse muoversi diversamente cercando nella 
funzione anonima l'oggetto collegato allo scope globale piuttosto che 
quello ritornato) ma se mi dici che effettivamente è così la cosa mi 
tranquillizza.
 
Grazie per tutte le spiegazioni e per il tempo che mi hai dedicato.

 "javascript:..."?
 
Quello di cui sopra, appunto. Ma sarebbe comunque da sconsigliarsi come
la peste.

 eseguire,
 
Scusami, ma è un motivo un po' stupido. Come se l'utente sapesse che
cosa fa quel codice :) Posso sempre avere nella mia bookmarklet, un link
tipo:
 
    <a href="javascript:apriFotoConEffettoFigo3D()">...</a>
 
e poi dentro la funzione, ovviamente minimizzata con tools apposta "per
avere codice più compatto, non certo per oscurarlo", sfrutto una
vulnerabilità di qualche sito per inviare i cookie di autenticazione al
mio sito remoto.
 
Non capisco in cosa possa tranquillizzare vedere il nome di una funzione
sulla barra di stato. Capisco molto bene per i link effettivi, che
portano a siti e pagine web, ma per quanto riguarda funzioni non ne vedo
il senso, dato che posso chiamarle come diavolo mi pare e non c'è una
relazione tra il nome e quello che fanno; come in vece c'è con i link a
pagine.
 
Lo pseudo protocollo javascript:, tranne rari casi, dovrebbe essere
evitato sempre, specialmente dai link.

 Grazie per tutte le spiegazioni e per il tempo che mi hai dedicato.
 
Figurati, il NG ï¿œ qui per questo. :)
 
Ti lascio con una delle metafore sul global scope che piï¿œ preferisco:
 
"Lo scope globale ï¿œ come un cesso pubblico: eviti in tutti i modi di
usarlo, e quelle volte che davvero non puoi farne a meno cerchi di
toccarlo il meno possibile."

 comportasse in modo equivalente?
 
Il fatto è che dentro la funzione anonima sono definite un bel numero di 
funzioni, e avevo "immaginato" che JS potesse "andare" subito a quella 
esportata mentre avesse dovuto leggere tutto prima di "beccare" il 
return. Lascia perdere, idiozie di una mente confusa. :)
 

 la differenza.
 
Ho scoperto l'arcano. In FF 7.0.1 funziona, in FF 3.6 no. D'accordo, mi 
hai già detto che dovrei aggiornare, ma sono legato quando ci si abitua 
alle comodità di un'estensione che non è compatibile con le versioni 
successive, si diventa ostinati. :)
E poi, facendo tutto questo lavoro per me, piuttosto che per gli altri, 
mi sento meno vincolato a rispettare le regole del vero sviluppatore.

 tipo:
 
Sï¿œ, lo so, ma come dicevo prima, certe cose le faccio piï¿œ per me che per 
gli altri. Anch'io non mi fiderei a giudicare il codice altrui in base 
al nome delle funzioni, ma visto che questo l'ho scritto io, il fatto di 
vederlo a video mi serve e come forma di debug e come comprensione di 
quello che fanno certi collegamenti.
 
Comunque il tuo messaggio ï¿œ chiaro: href="javascript:..." non si fa.

 return. Lascia perdere, idiozie di una mente confusa. :)
 
Lascio perdere davvero perché non ti seguo. :)

 mi sento meno vincolato a rispettare le regole del vero sviluppatore.
 
Non ti capisco, io la vedo proprio all'opposto: ovvero, facendo le cose
per gli altri, mi senti più vincolato a dover usare vecchie versioni di
browser, lente, con meno funzionalità, perché la mia base utenti usa
quelle. Ma a maggior ragione se faccio le cose per me stesso, cerco di
avere il meglio, perché non sono vincolato dalla mia base utenti.

 Comunque il tuo messaggio ï¿œ chiaro: href="javascript:..." non si fa.
 
"Generalmente" non si fa. ï¿œ bene tenersi un margine, anche quando si
parla di MAI E POI MAI, vuol dire di solito "nel 99.99% dei casi". ;)

 posso magari dirti se esiste una strada migliore.
 
La struttura del mio codice è questa:
 
(function() {
 
dichiarazioni iniziali
 
function f1(p1) {
...
}
 
function f2(p2) {
...
}
 
...
 
function fn(pn) {
...
}
 
function cuore(el) {
   if (typeof el === "number" ) {
     // la funzione è richiamata da onlick;
     // a seconda del parametro, eseguo delle istruzioni particolari
     // se el=0 allora... se el=1 allora... eccetera
     ...
   }
   else {
     // la funzione è richiamata da addEventListener
     // identifico l'elemento che l'ha chiamata,
     // in caso di link annullo il clic e manipolo opportunamente
     var c=el.target;
     if (!(c.tagName=="A")) return;
     el.preventDefault();
     ...
   }
 
   blocco istruzioni comuni
 
}
 
// intervengo sul DOM creando un div (div) contenente elementi
// (el0,el1,...) che compongano una "specie" di gui
// populo il div con i link della pagina sottostante
 
blocco istruzioni
 
// faccio in modo che alcuni dei precedenti oggetti dom scatenino la 
funzione cuore
 
document.getElementById("el0").onclick=function(){cuore(0)};
document.getElementById("el1").onclick=function(){cuore(1)};
...
 
// intercetto i clic sui link dentro il div che ho creato e li manipolo
 
div.addEventListener("click",cuore,false);
 
})()
 

 avere il meglio, perché non sono vincolato dalla mia base utenti.
 
Sì, ma come ti ho detto sono io a essermi consapevolmente vincolato a FF 
3.6. Questo piccolo programma è partito come un gioco e tra un po' se 
prosegue con tutti i raffinamenti del caso mi tocca pubblicarlo... :)

 *stai* usando le closure. :)
 
Ok. Allora considero tutto il contrario di ciï¿œ che avevo inteso e arrivo 
alla closure. :)
Dovessi ripetere ora, direi che con la mia domanda iniziale chiedevo 
come esporre una funzione locale dentro una funziona anonima allo scope 
globale, cosa non molto indicata e che ho evitato producendo la closure 
della funzione anonima.

 div.addEventListener("click",cuore,false);
 
Mi spieghi mo', perché usi `addEventListener` in un caso, e `onclick`
nell'altro? :) Sii consistente, usa sempre o `addEventListener`
(consigliato) oppure `onclick`.
 

 prosegue con tutti i raffinamenti del caso mi tocca pubblicarlo... :)
 
E allora ti toccherï¿œ farlo per FF7, 8 e 9 ;) Altro che 3.6. :)

 alla closure. :)
 
Una closure la crei quando esporti il riferimento di una funzione,
creata dentro un'altra funzione, in uno scope diverso. Nel tuo caso,
come ti ho scritto in un post precedente, questo lo fai associando ad
eventi DOM delle funzioni create nel modo scritto sopra.
 
Ancora, ricordi:
 
    !function (exports) {
        exports.foo = function() {}
    }(this);
 
    // oppure
 
    this.foo = function() {
        return function() {};
    }()
 
?
 
Ecco, e che differenza c'ï¿œ scusa, ad avere "foo" oppure "onclick"?
 
    !function(exports) {
        exports.onclick = function() {}
    }(document.body);
 
    document.body.onclick = function(){
        return function() {};
    }()
 
?
 
Nel tuo caso, che fai:
 
    !function() {
        document.body.onclick = function() {};
    }()
 
Altro non ï¿œ che l'equivalente di:
 
    !function(exports) {
        exports.document.body.onclick = function() {};
    }(this)
 
Perchï¿œ nei browser il global object ï¿œ `window` ed ï¿œ considerato
implicito (in quanto global object). Quindi quando scrivi:
 
    document.getElementById(...);
    alert(...);
 
Quello che stai facendo ï¿œ:
 
    window.document.getElementById(...);
    window.alert(...);
 
Che, se sei nel global scope, ï¿œ equivalente a:
 
    this.document.getElementById(...);
    this.alert(...);
 
Spero che ti sia piï¿œ chiaro adesso. :)

 gruppi non attivi completamente dalla memoria e gestirli a mo' di bookmark.
 
Che ï¿œ poi il principio di BarTab. Ma finchï¿œ non ci arrivano...

 (consigliato) oppure `onclick`.
 
Perché ho dimenticato di dirti una cosa importante. Nella pagina io 
leggo codice html "grezzo" (cioè: c'è un elemento della pagina che 
contiene una stringa di testo del tipo "<div>...</div><p>...</p>" e via 
dicendo) che io assegno brutalmente alla proprietà innerHTML del div.
Se avessi tempo e capacità, dovrei costruire un parser html coi fiocchi 
per ricostruire il contenuto descritto dal codice html via JS, ma ho 
deciso di essere tranchant e di copiare tutto così com'è via div.innerHTML=
Sì, so che così sporco il DOM. Sì, so che non è una bella cosa. Però 
questo mi costa 1, la perfezione mi costa 100. Ho deciso di spendere 1 e 
basta. Ecco il perché dell'addEventListener.
Analogamente, costruisco la gui allo stesso modo (contravvenendo a una 
tua precedente indicazione, questa me la ricordo). Come prima, so che 
non è cosa ben fatta perché sporco il DOM. Ma tanto siccome lo sporco 
già per la scelta di cui sopra (e lo sporco parecchio), tanto valeva 
risparmiare tempo. Ecco perché uso gli id per identificare gli elementi: 
perché non li ho creati esplicitamente via document.createElement.

 Che ï¿œ poi il principio di BarTab. Ma finchï¿œ non ci arrivano...
 
ï¿œ giï¿œ stato implementato. Sapevo che ci stavano lavorando, ma stasera ho
avuto la conferma che le modifiche sono giï¿œ in Firefox.

 perché non li ho creati esplicitamente via document.createElement.
 
Come ho detto, è irrilevante. Li crei te comunque, sai come sono e DOVE
sono, e quindi come referenziarli.

 DIV proprio al body. Non puoi sapere quali regole andrai ad ereditare.
 
E' vero. Ma quasi tutti i bookmarklet che conosco usano div, e mi pare 
quindi che corrano lo stesso pericolo. L'ho sempre considerato un 
rischio da accettare.
Tu proponi di creare un iframe. Ma come fai a rispettare la "same origin 
policy" se lavori su un sito terzo?
 

 avuto la conferma che le modifiche sono giï¿œ in Firefox.
 
Hai un link da segnalarmi?
Poi, mi rendo conto che sembro reticente, perchï¿œ aggiungo un pezzo per 
volta, ma prima ho tralasciato di dirti, perchï¿œ mi sembrava superfluo, 
un'altra cosa.
Io non uso i tab groups (se ho ben capito a cosa ti riferisci) di FF 4. 
Possono essere considerati bellissimi dal 99,99% degli utenti, ma io li 
trovo scomodi.
Io uso TabGroups Manager. Con un clic passo da un gruppo all'altro. Con 
un drag&drop sposto una scheda da un gruppo a un altro, senza bisogno di 
passare alla schermata dove ci sono le anteprime di tutte le schede. 
TabGroups Manager mi accompagna oramai da qualche anno. Mi ha abituato 
bene e nonostante la minor resa estetica rispetto ai tab groups di FF 4 
e altre pecche che puï¿œ avere soddisfa alla perfezione le mie abitudini 
di navigazione.

 trovo scomodi.
 
Puoi anche non usarli. Io li uso il giusto. Te li ho segnalati giusto
perché mi sembravano parte di quelle feature di cui sentivi la mancanza.
Mentre adesso l'impressione che ho è che non vuoi fare l'upgrade un po'
per partito preso. Che per carità, va bene, l'utente ha la libertà di
fare quel che è meglio per lui.
È che, come disse Christian Heilmann, per Mozilla non importa se usi
Firefox o un altro browser, fintanto che è un browser che usa open web
standars ed è un browser moderno e sicuro. Il fatto è che Firefox 3.6
non è più queste cose, ed è anche questa la ragione per cui non è più
supportato da Mozilla.
Come ho detto in precedenza, Firefox 3.6 è un po' l'IE6 di Mozilla.

 Tu proponi di creare un iframe. 
 
No, io propongo di usare qualcosa di diverso dai DIV. Avere tag tuoi e/o
un namespace tuo. Ovviamente sarebbero comunque soggetti alle regole CSS
di qualcuno che definisce "*", ma già riduci abbondantemente il problema.
 
Ti ho suggerito di creare un iframe solo se proprio vuoi usare i markup
di HTML. In alcuni casi è preferibile. Ovviamente la bookmarklet in
questo caso deve rispettare la SOP, e quindi deve avere una natura
conseguente alla cosa (es. una bookmarlet che fa il retweet di un sito o
che aggiunge la pagina corrente a google bookmark ha solo bisogno di
dati in input dalla pagina corrente, non di impostare dati in ouput
sulla stessa).
 
Puoi, ovviamente, anche creare delle regole CSS che abbiano una
specificità maggiore per i tuoi elementi, e nelle quali resetti tutte, o
il grosso, delle regole CSS che potrebbero avere.
 
Puoi anche usare un mix di tutte queste cose, per avere un buon margine
di sicurezza.
 
Io solitamente bookmarklet che mi sballano la pagina tendo a non usarle,
a meno che non siano il loro scopo e che quindi non possano far casino
(cambiare il CSS per una maggiore leggibilità, ad esempio); oppure che
non siano roba divertente da usare una volta così per fare (tipo
asteroid o katamari damacy).
Preferisco quelle che aprono piuttosto una popup – o appunto, se lo vuoi
più integrato nel sito web, un iframe.

 Come ho detto in precedenza, Firefox 3.6 è un po' l'IE6 di Mozilla.
 
Non voglio scatenare un flame, ma non penso di non voler aggiornare "per 
partito preso". Semplicemente, la penso diversamente da te.
Personalmente, Firefox mi piace tantissimo. Non riesco a concepire la 
navigazione senza Firefox. Non mi piace IE, mi piace Chrome ma meno 
perché non riesco ad adattarlo al mio modo di navigare, per motivi sui 
quali non mi dilungo.
Quindi per me è FF o niente altro. Ciononostante, FF ha dei difetti 
enormi. Il primo, gigantesco, è che mangia tanta di quella ram da fare 
paura. In poche ore arrivo a 2Gb di ram. E il fatto che gestisca male la 
ram non lo dico solo io, ne parlano in tantissimi.
Per come la vedo io, se mi permetti di usare espressioni colorite, pur 
ribadendo la mia preferenza per FF, gli sviluppatori di FF hano lavorato 
alla membro di segugio. Hanno costruito un mostro su un nucleo 
malfunzionante. Non vorrei essere frainteso: li capisco. Per stare al 
passo dei concorrenti, si da la precedenza a implementare funzionalità 
nuove piuttosto che a correggere impostazioni vecchie sbagliate. Per 
inciso: perché io dovrei preoccuparmi così tanto di scrivere codice 
perfetto quando il browser stesso, come tu ammetti, ha dei memory leak 
legati al non corretto "scaricamento" delle pagine?
Poi ci sono le estensioni, che sono forse il motivo principale per cui 
uso FF: riesco a trasformarlo in ciò che mi piace. Anche qui problemi di 
memoria (se FF impazzisce, può trattarsi di un'estensione scritta male; 
ma per me ha più colpa FF, perché in ogni caso penso che sia il 
programma a dovermi proteggere dal codice scritto male da altri, che 
siano gli sviluppatori di siti o di estensioni).
Comunque, mi pare indubitabile che FF abbia avuto, e abbia ancora 
successo, perché ognuno riesce a personalizzarlo con le estensioni che 
preferisce. Che però, da un momento all'altro, passando da una versione 
alla successiva, possono smettere di funzionare. Ecco, mi sembra che un 
punto sia questo: qualcuno preferisce un browser moderno e sicuro (ma 
sempre brutalmente bulimico), qualcun altro preferisce correre dei 
rischi perché col tempo si è fatto un vestito che non vuole dismettere 
da un giorno all'altro, e è disposto ad aspettare il giorno in cui il 
"browser moderno e sicuro" (che fino a poco fa esauriva la ram del mio 
pc obbligandomi a tempi di attesa e di risposta assurdi) glielo lascerà 
ancora indossare.

 sempre brutalmente bulimico),
 
Mi dispiace, ma non sono d'accordo né col bulimico né soprattutto col
brutalmente.
Come ho detto, a me sembra più che ci siano persone che non amano i
cambiamenti, e preferiscono restare con ciò che hanno, anche se non è il
massimo (in termini di consumo memoria, performance, eccetera) perché
ormai sono abituati a quello.
E posso capirlo. Magari non è una cosa che condivido, ma come ho detto
l'utente ha sempre la libertà di decidere cosa è meglio per sé. Non
discuto su questo.

 discuto su questo.
 
Posso essere d'accordo con te, più o meno. Il più o meno dipende dal 
fatto che l'abitudine non dipende da pigrizia o inerzia, ma dalla 
volontà di non rinunciare a delle comodità che si hanno. Cioè: se 
migliori il programma sotto diversi aspetti, ma mi togli alcune delle 
funzionalità per cui lo trovavo così buono, non faccio i salti di gioia 
a cambiare versione, anzi, posso decidere di rimanere con quella vecchia.
Per esempio, io trovo odioso il pulsante principale come è concepito in 
FF 4, ma mi fa piacere che ci sia la possibilità di tornare al layout 
precedente. Non ci fosse stato.... avresti giudicicato la mia decisione 
incomprensibile...
 
Comunque, dammi tempo: come ti ho detto, non smetto mai di controllare 
le novità in casa Mozilla.

 incomprensibile...
 
Lavorando io su Mac, non ho il problema del "pulsante principale" di cui
parli, temo. :)

 aggiornare così il browser.
 
Sono nella prima! Metto il punto esclamativo perché per l'offerta che mi 
fai strabuzzo gli occhi. Come ti dicevo, dammi un po' di tempo, testerò 
a fondo FF 7 per vedere come funziona BarTab Lite, e poi magari mi 
rifaccio vico con un nuovo thread.
Grazie mille intanto della tua disponibilità!
 

 Grazie mille intanto della tua disponibilità!
 
Figurati, ci mancherebbe. :) Anche questo fa parte del mio lavoro.
Fai un fischio quando migrerai, allora..!
 

 (non Lite) su FF4?
 
Sì, è così. Mi sa che ancora una volta mi sono spiegato male. Io sono 
partito con BarTab, e tu con BarTab Lite. Comunque con un po' di calma 
provo l'una e l'altra e quindi mi accerto di come stanno effettivamente 
le cose.
 
Grazie ancora per tutto il resto.

 (consigliato) oppure `onclick`.
 
Sto rivedendo questo punto.
Se uso una funzione anonima
 
el.addEventListener("click",function{alert("OK")}, false);
 
come faccio a rimuoverla?
 
el.removeEventListener("click",function{alert("OK")});
 
?
 
E se sbaglio e scrivo
 
el.removeEventListener("click",function{alert("OK2")});
 
?
 
Con .onclick non avevo questo dubbio, impostavo .onclick="";

 Con .onclick non avevo questo dubbio, impostavo .onclick="";
 
Cosa sbagliata, dato che `onclick` non è una stringa. Dovresti
impostarlo a `undefined` – `null` in alcuni browser.

 riferimento per farlo.
 
Cosa mi dici dell'ultimo post in fondo alla pagina
http://www.codingforums.com/archive/index.php/t-5909.html
 
?

 ?
 
In fondo a questa pagina mi sembra si dica la stessa cosa: assegnare  la 
funzione anonima a una variabile.
http://stackoverflow.com/questions/256754/how-to-pass-arguments-to-addeventlistener-listener-function
 

 ?
 
In che senso, scusa? Dice quello che ti ho scritto sopra – ovvero si
salva il riferimento della funzione per poterla rimuovere in un secondo
momento – solo che lo fa in modo grezzo – `bar` non è dichiarata, e
assegnarla in quel modo non è qualcosa che consiglierei di fare.
 

 
http://stackoverflow.com/questions/256754/how-to-pass-arguments-to-addeventlistener-listener-function
 
 
Continuo a non seguirti, scusami. Mi sono forse spiegato male nel mio
post? Se hai bisogno di rimuovere un listener usando `addEventListener`,
*devi* avere un riferimento. Se associ una funzione anonima non hai
alcun riferimento per rimuoverla. Ovviamente, se la funzione non è
anonima, o ti salvi il riferimento da qualche parte, puoi rimuoverla. La
differenza che sta tra:
 
    function bar() {
 
    }
 
    el.addEventListener("click", bar, false);
 
E:
 
    var bar = function() {
 
    }
 
    el.addEventListener("click", bar, false);
 
È che nel nel primo caso hai una dichiarazione di funzione, nel secondo
caso un'espressione di funzione. Ma in entrambi i casi hai `bar` come
riferimento alla funzione, nello scope in cui sei. La differenza è che
nel secondo caso scrivi più codice, e nei browser che supportano
l'attributo `name` per le funzioni non ti restituisce niente. Quindi io
consiglio sempre la prima in questo genere di situazioni. Buona pratica
in JS / ES5 strict (dato che non puoi usare callee), suggerisce di dare
sempre un nome alla funzione anche nel secondo caso:
 
    var bar = function onClick(){
 
    }
 
    el.addEventListener("click", bar, false);
 

 post?
 
Ne ho scritti due insieme, prima della tua risposta. Forse è dipeso da 
questo.
 
Comunque farò come hai detto.