Perché passare grandi funzioni anonime come argomenti ad altre funzioni così ampiamente accettate in JavaScript?


27

Ho un'opinione (che sono sicuro che sarà condivisa da alcuni) che passare funzioni anonime che contengono più di poche righe di codice, poiché gli argomenti ad altre funzioni influiscono drasticamente sulla leggibilità e sull'autocumentazione, al punto che ritengo essere molto meglio per chiunque probabilmente usi il codice per dichiarare semplicemente una funzione con nome. O almeno assegnare quella funzione anonima a una variabile prima di dichiarare la funzione principale

Tuttavia, molte librerie JavaScript (jQuery, d3.js / NVD3.js) solo per fare un paio di esempi, usano grandi funzioni in questo modo.

Perché questo è così ampiamente accettato in JavaScript? È una cosa culturale o ci sono dei vantaggi che mi mancano, il che renderebbe l'uso più preferito rispetto alla dichiarazione di una funzione con nome?


1
Probabilmente ha molto a che fare con l'uso delle chiusure . Potrebbe anche avere a che fare con il non voler esporre la funzione reale al mondo esterno (motivo per cui è anonimo).
Robert Harvey,

3
@RobertHarvey In altre parole, è una soluzione alternativa per JavaScript che non ha pubblico e privato ?
Mason Wheeler,

2
In molti posti, una grande funzione anonima assomiglia di più a un blocco e generalmente si sente abbastanza bene quando ci si abitua. Le regole di scoping supportano persino la sensazione di blocco.

5
@MasonWheeler: dipende dalla tua prospettiva. Un programmatore Scheme o ECMAScript potrebbe dire questo publice privatesono soluzioni alternative per non avere chiusure adeguate.
Jörg W Mittag,

1
@ JörgWMittag Hooray for Racket, sponsor ufficiale della lingua di XKCD 927!
Mason Wheeler,

Risposte:


23

Tre motivi principali a cui posso pensare:

  1. Accesso ambito genitore
  2. vita privata
  3. Riduzione dei nomi definiti in ambiti superiori

Accesso ambito padre: le definizioni delle funzioni incorporate consentono al codice incorporato di accedere alle variabili definite negli ambiti padre. Questo può essere molto utile per molte cose e può ridurre la quantità o la complessità del codice se fatto correttamente.

Se si inserisce il codice in una funzione definita al di fuori di questo ambito e quindi si chiama il codice, è necessario passare qualsiasi stato padre a cui si desidera accedere alla funzione.

Privacy: il codice all'interno di una definizione anonima incorporata è più privato e non può essere chiamato da altro codice.

Riduzione dei nomi definiti in ambiti più alti: questo è molto importante quando si opera nell'ambito globale, ma una dichiarazione anonima in linea impedisce di definire un nuovo simbolo nell'ambito attuale. Poiché Javascript non richiede in modo nativo l'uso di spazi dei nomi, è saggio evitare di definire simboli più globali di quelli minimamente richiesti.


Editoriale: sembra essere diventato una cosa culturale in Javascript in cui dichiarare qualcosa di anonimo in linea è in qualche modo considerato "migliore" rispetto alla definizione di una funzione e alla sua chiamata anche quando l'accesso all'ambito genitore non viene utilizzato. Ho il sospetto che questo inizialmente fosse a causa del problema globale dell'inquinamento dello spazio dei nomi in Javascript, quindi forse a causa di problemi di privacy. Ma ora si è trasformato in qualcosa di culturale e puoi vederlo espresso in molti enti pubblici di codice (come quelli che menzioni).

In linguaggi come il C ++, molti probabilmente considererebbero una pratica tutt'altro che ideale avere una funzione gigante che si estende su molte pagine / schermate. Naturalmente, C ++ ha lo spazio dei nomi integrato, non fornisce l'accesso all'ambito padre e ha funzionalità di privacy, quindi può essere completamente motivato dalla leggibilità / manutenibilità, mentre Javascript deve usare l'espressione del codice per ottenere la privacy e l'accesso all'ambito padre. Quindi, JS sembra essere stato motivato in una direzione diversa ed è diventato in qualche modo una cosa culturale all'interno della lingua, anche quando le cose che hanno motivato quella direzione non sono necessarie in un caso specifico.


Dato che uno sviluppatore C ++ si è recentemente trasferito su JS per gran parte del mio lavoro, questa risposta ha molto senso, in particolare il punto di "accesso all'ambito padre" - ha davvero il potere di semplificare notevolmente il tuo codice. Uno nitpick - C ++ fornisce l'accesso all'ambito padre in C ++ 11 lambdas :) Sicuramente +1 però.
Comandante Coriandolo Salamander

8

Le funzioni anonime sono utilizzate per molti più scopi in JavaScript rispetto alla maggior parte delle lingue.

Innanzitutto, vengono utilizzati per la spaziatura dei nomi e l'ambito del blocco. Fino a poco tempo fa JavaScript mancava di moduli o di qualsiasi altro tipo di meccanismo di spaziatura dei nomi che ha portato all'utilizzo di funzioni anonime per fornire tale funzionalità tramite il Pattern del modulo. Non ci sarebbe assolutamente alcun vantaggio nel nominare queste funzioni. Su una scala più piccola, a causa della mancanza di scoping a blocchi di JavaScript fino a poco tempo fa, è stato utilizzato un modello simile per imitare lo scoping a blocchi; in particolare nel corpo dei cappi. L'uso di una funzione con nome in questo caso sarebbe attivamente offuscato.

In secondo luogo, e le funzioni anonime meno specifiche di JavaScript vengono spesso utilizzate con funzioni di ordine superiore che imitano le strutture di controllo. Ad esempio, il eachmetodo di jQuery . Dubito che tu astragga ogni corpo di loop o if-branch in una funzione ogni volta che è lunga più di qualche riga. La stessa logica si applica in questo caso.

Un'ultima ragione è che la programmazione basata su eventi è comune in JavaScript che tende a portare a un codice di stile di passaggio di continuazione involontario . Si effettua una chiamata AJAX e si registra una richiamata che, una volta eseguita, effettuerà un'altra chiamata AJAX e registrerà una richiamata ecc. Se le chiamate fossero sincrone anziché asincrone, si tratterebbe solo di una sequenza lineare di codice in un singolo ambito lessicale . Ancora una volta, dubito che vorrai astrarre ogni poche righe di codice lineare in una funzione.

Ci sono anche fattori culturali e, per le ragioni sopra menzionate, tra le altre, le funzioni anonime sono molto più comuni in JavaScript rispetto a molte altre lingue e sono utilizzate in modo più comodo / rilassato rispetto a molte altre lingue.


Le mie strutture, forse ingenue, nella codifica C ++ hanno talvolta preso i principi della codifica basata su eventi e dei callback da JavaScript tramite std :: function e lambdas. Nel mio caso, è parzialmente perché sto facendo il codice dell'interfaccia utente in C ++ e non voglio eseguire operazioni di blocco. Sono curioso di sapere se le pratiche di JavaScript sono semplicemente utili a chiunque, purché il linguaggio le supporti bene.
Katana314,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.