Pattern del modulo JavaScript con esempio [chiuso]


136

Non riesco a trovare esempi accessibili che mostrino come due (o più) moduli diversi sono collegati per lavorare insieme.

Quindi, vorrei chiedere se qualcuno ha il tempo di scrivere un esempio che spiega come i moduli lavorano insieme.


Tutto è cambiato negli ultimi quattro anni, ma grazie alla zelante eccessiva moderazione, queste informazioni obsolete rimarranno per sempre . Ecco la pagina di MDN sui moduli ES6.
bbsimonbb,

Risposte:


256

Per avvicinarsi al modello di progettazione modulare, è necessario prima comprendere questi concetti:

Espressione di funzione immediatamente richiamata (IIFE):

(function() {
      // Your code goes here 
}());

Esistono due modi per utilizzare le funzioni. 1. Dichiarazione di funzione 2. Espressione di funzione.

Qui stanno usando l'espressione della funzione.

Che cos'è lo spazio dei nomi? Ora, se aggiungiamo lo spazio dei nomi al pezzo di codice sopra, allora

var anoyn = (function() {
}());

Cos'è la chiusura in JS?

Significa che se dichiariamo una funzione con un ambito variabile / all'interno di un'altra funzione (in JS possiamo dichiarare una funzione all'interno di un'altra funzione!), Conterà sempre tale ambito funzione. Ciò significa che qualsiasi variabile nella funzione esterna verrà sempre letta. Non leggerà la variabile globale (se presente) con lo stesso nome. Questo è anche uno degli obiettivi dell'utilizzo del modello di progettazione modulare evitando conflitti di denominazione.

var scope = "I am global";
function whatismyscope() {
    var scope = "I am just a local";
    function func() {return scope;}
    return func;
}
whatismyscope()()

Ora applicheremo questi tre concetti che ho menzionato sopra per definire il nostro primo modello di progettazione modulare:

var modularpattern = (function() {
    // your module code goes here
    var sum = 0 ;

    return {
        add:function() {
            sum = sum + 1;
            return sum;
        },
        reset:function() {
            return sum = 0;    
        }  
    }   
}());
alert(modularpattern.add());    // alerts: 1
alert(modularpattern.add());    // alerts: 2
alert(modularpattern.reset());  // alerts: 0

jsfiddle per il codice sopra.

L'obiettivo è nascondere l'accessibilità variabile al mondo esterno.

Spero che questo ti aiuti. In bocca al lupo.


sarebbe meglio nominare iife? per scopi semantici e una migliore tracciabilità dello stack? cambierebbe qualcosa nel codice?
Jeroen,

2
Il tuo primo esempio (function() { /* Your code goes here */}());è in realtà un IIFE (immediatamente Invocando espressione di funzione), ok è anonimo coz non ha un nome così si potrebbe anche voler chiamarlo un IIAFE (immediatamente Invocare Anonimo Function Expression) vedere di più su IIFE su stackoverflow.com/questions/ 2421911 /…
Adrien,

perché è stata utilizzata la dichiarazione di ritorno? se omettiamo return {}, la funzione di aggiunta e ripristino sarebbe pubblica e suppongo che possano accedere alla somma delle variabili locali? ho ragione?
Mou,

il tuo secondo esempio sembra un oggetto o non ho ragione?
The Reason,

4
Questo non risponde alla domanda del PO. È una descrizione del modello del modulo, non un esempio di come più moduli possono lavorare insieme come voleva l'OP.
Erik Trautman,

39

Consiglio vivamente a chiunque entri in questa materia di leggere il libro gratuito di Addy Osmani:

"Apprendimento dei modelli di progettazione JavaScript".

http://addyosmani.com/resources/essentialjsdesignpatterns/book/

Questo libro mi ha aiutato immensamente quando stavo iniziando a scrivere JavaScript più gestibili e lo uso ancora come riferimento. Dai un'occhiata alle sue diverse implementazioni del modello di modulo, le spiega davvero bene.


Consiglio anche di leggere il mio articolo sul "Definitive Module Pattern" che non è trattato nel libro di Addy Osmani: github.com/tfmontague/definitive-module-pattern
tfmontague

1
Come si confronta con "JavaScript Patterns" di Stoyan Stefanov
JohnMerlino il

4
Il libro di Stoyan è molto più completo. Copre più di semplici schemi di alto livello ma parla anche più in profondità di altre migliori pratiche di JS.
Noviziato del codice

1
recensioni di "Apprendimento dei modelli di progettazione JavaScript" amazon.com/product-reviews/1449331815
Adrien Be

3
recensioni di "JavaScript Patterns" di Stoyan Stefanov amazon.com/product-reviews/0596806752 . Nota: che sembra molto meglio di quello di "Imparare JavaScript Design Patterns"
Adrien Be

19

Ho pensato di ampliare la risposta di cui sopra parlando di come potresti adattare i moduli in un'applicazione. Ne avevo letto nel libro di Doug Crockford, ma essendo nuovo a JavaScript era tutto ancora un po 'misterioso.

Vengo da ac # background quindi ho aggiunto un po 'di terminologia che trovo utile da lì.

html

Avrai qualche tipo di file html di livello superiore. Aiuta a pensare a questo come al tuo file di progetto. Ogni file javascript che aggiungi al progetto vuole entrare in questo, sfortunatamente non hai il supporto degli strumenti per questo (sto usando IDEA).

È necessario aggiungere file al progetto con tag di script come questo:

        <script type="text/javascript" src="app/native/MasterFile.js" /></script>
        <script type="text/javascript" src="app/native/SomeComponent.js" /></script>

Sembra che il collasso dei tag causi il fallimento delle cose - mentre sembra che xml sia davvero qualcosa con regole più folli!

File dello spazio dei nomi

MasterFile.js

myAppNamespace = {};

questo è tutto. Questo è solo per aggiungere una singola variabile globale per il resto del nostro codice in cui vivere. Puoi anche dichiarare spazi dei nomi nidificati qui (o nei loro file).

Modulo (s)

SomeComponent.js

myAppNamespace.messageCounter= (function(){

    var privateState = 0;

    var incrementCount = function () {
        privateState += 1;
    };

    return function (message) {
        incrementCount();
        //TODO something with the message! 
    }
})();

Quello che stiamo facendo qui è assegnare una funzione di contatore messaggi a una variabile nella nostra applicazione. È una funzione che restituisce una funzione che eseguiamo immediatamente .

concetti

Penso che aiuti a pensare alla linea superiore di SomeComponent come allo spazio dei nomi in cui stai dichiarando qualcosa. L'unica avvertenza è che tutti i tuoi spazi dei nomi devono apparire prima in qualche altro file: sono solo oggetti radicati dalla nostra variabile dell'applicazione.

Al momento ho fatto solo piccoli passi con questo (sto eseguendo il refactoring di un normale javascript da un'app extjs in modo da poterlo testare) ma sembra abbastanza bello in quanto è possibile definire piccole unità funzionali evitando il quagmire di 'questo ' .

È inoltre possibile utilizzare questo stile per definire i costruttori restituendo una funzione che restituisce un oggetto con una raccolta di funzioni e non lo chiama immediatamente.


6

Qui https://toddmotto.com/mastering-the-module-pattern puoi trovare lo schema spiegato in dettaglio. Vorrei aggiungere che la seconda cosa su JavaScript modulare è come strutturare il codice in più file. Molte persone possono consigliarti qui di andare con AMD, ma posso dire per esperienza che finirai per avere una risposta lenta della pagina a causa di numerose richieste HTTP. La via d'uscita è la pre-compilazione dei moduli JavaScript (uno per file) in un singolo file seguendo lo standard CommonJS. Dai un'occhiata agli esempi qui http://dsheiko.github.io/cjsc/


Tutte le implementazioni AMD forniscono anche la precompilazione in un singolo file.
I-Lin Kuo,

1
Ciò è corretto, ma il file ottimizzato risultante richiede la libreria del caricatore (appena ricontrollato con r.js v2.1.14), che di solito è piuttosto pesante. Non appena abbiamo compilato il codice non abbiamo bisogno di risolvere dipendenze caricate in modo asincrono, non abbiamo bisogno di questa libreria. Basta considerare: avvolgiamo i moduli in AMD, questo significa asincrono. caricamento, quindi compilarli in un singolo file (nessun caricamento separato più), ma caricare l'intera libreria per risolverli (cosa è ridondante ora). Non sembra un modo ottimale per me. Perché AMD a tutti quando non cariciamo in modo asincrono?
Dmitry Sheiko,

almond.js offre un caricatore di peso più piccolo per il codice di produzione finito rispetto a RequireJS, ma in termini comparativi, il vantaggio in termini di prestazioni di non fare una sola richiesta HTTP supera di gran lunga il costo dell'aggiunta del codice del caricatore al modulo, quindi mentre è meno ottimale, è su scala molto più piccola. La domanda, secondo me, dovrebbe essere capovolta: perché assumere la sincronicità quando il browser non lo è? In realtà sono dell'opinione che sia RequireJS che CommonJS dovrebbero avere un'implementazione promettente integrata.
I-Lin Kuo,

Entrambi i formati sono percorsi validi per CommonJS Modules / 2.0 e forniscono la stessa scalabilità. Quanto a me - gestire i moduli CJS / 1.1 (questo è ciò che intendo per CommonJS) è molto più semplice, il codice sembra più pulito.
Dmitry Sheiko,

Ho riscontrato vantaggi di AMD come: * può caricare più di un semplice file JavaScript; * alias di percorso; Bene, CommonJS Compiler risolve questi problemi: carica dipendenze non JavaScipt / JSON come dati e può essere fornito con la configurazione di build (compresi gli alias). L'unico svantaggio che richiede la costruzione. Ma oggigiorno tutti costruiscono comunque il progetto per i pre-processori CSS. Quindi si tratta solo di aggiungere un'attività extra per Grunt / Gulp ...
Dmitry Sheiko

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.