2013-05-05 22 views
174

In questa pagina (http://docs.nodejitsu.com/articles/getting-started/what-is-require), si afferma che "Se si desidera impostare l'oggetto Export su una funzione o un nuovo oggetto, è necessario utilizzare l'oggetto module.exports. "Differenza tra "module.exports" e "exports" nel sistema di moduli CommonJs

La mia domanda è perché.

// right 
module.exports = function() { 
    console.log("hello world") 
} 
// wrong 
exports = function() { 
    console.log("hello world") 
} 

I console.logged il risultato (result=require(example.js)) ed il primo è [Function] il secondo è {}.

Potrebbe spiegarci il motivo? Ho letto il post qui: module.exports vs exports in Node.js. È utile, ma non spiega il motivo per cui è stato progettato in questo modo. Ci sarà un problema se il riferimento delle esportazioni sarà restituito direttamente?

+4

Usa sempre 'module.exports'. –

+0

Penso che il seguente consiglio sopra suggerito permette di evitare questo problema. –

+0

@GabrielLlamas, quindi perché molti pacchetti utilizzano solo "esportazioni", ad esempio https://github.com/tj/consolidate.js/blob/master/lib/consolidate.js? – CodyBugstein

risposta

421

module è un oggetto JavaScript semplice con una proprietà exports. exports è una semplice variabile JavaScript che sembra essere impostata su module.exports. Alla fine del file, node.js fondamentalmente 'restituisce' module.exports alla funzione require. Un modo semplificato per visualizzare un file JS in nodo potrebbe essere questo:

var module = { exports: {} }; 
var exports = module.exports; 

// your code 

return module.exports; 

Se si imposta una proprietà su exports, come exports.a = 9;, che fisserà module.exports.a così perché gli oggetti vengono passati in giro come riferimenti in JavaScript, il che significa che se si impostano più variabili sullo stesso oggetto, esse sono tutti allo stesso oggetto; quindi lo exports e lo module.exports sono lo stesso oggetto.
Ma se si imposta exports su qualcosa di nuovo, non sarà più impostato su module.exports, quindi exports e module.exports non sono più lo stesso oggetto.

+6

Esatto, sono solo le basi dei tipi di riferimento. –

+4

Perché !? Perché si può leggere questo solo qui. Questo dovrebbe essere una tagline per ogni javaScript modulare. Grazie –

13

La risposta di Rene sulla relazione tra exports e module.exports è abbastanza chiara, si tratta di riferimenti javascript. Voglio solo aggiungere che:

Lo vediamo in molti moduli nodo:

var app = exports = module.exports = {};

Questo farà in modo che, anche se abbiamo cambiato module.exports, possiamo ancora usare le esportazioni, rendendo tali due variabili puntare allo stesso oggetto.

+0

Sono diventato confuso da questa spiegazione, gentile da elaborare? – GuyFreakz

+3

@GuyFreakz Non sono sicuro che questo parli della tua confusione, ma 'module.exports' e' exports' sono solo variabili separate, inizializzate per fare riferimento allo stesso oggetto. Se si modifica il riferimento a una variabile, le due variabili non fanno più riferimento alla stessa cosa. La riga di codice sopra assicura che entrambe le variabili siano inizializzate sullo stesso nuovo oggetto. –

+0

Un vero e proprio caso d'uso che tutti gli altri hanno mancato su @fengshuo. Grazie! –

15

Inoltre, uno cose che possono aiutare a capire:

math.js

this.add = function (a, b) { 
    return a + b; 
}; 

Client.js

var math = require('./math'); 
console.log(math.add(2,2); // 4; 

Grandi, in questo caso:

console.log(this === module.exports); // true 
console.log(this === exports); // true 
console.log(module.exports === exports); // true 

Quindi, per impostazione predefinita, "questo" i in realtà è uguale a module.exports.

Tuttavia, se si cambia l'implementazione per:

matematica.js

var add = function (a, b) { 
    return a + b; 
}; 

module.exports = { 
    add: add 
}; 

In questo caso, funzionerà bene, tuttavia, "questo" non è uguale a module.exports più, perché un nuovo oggetto è stato creato.

console.log(this === module.exports); // false 
console.log(this === exports); // true 
console.log(module.exports === exports); // false 

E adesso, cosa sarà restituito dalla richiede è quello che è stato definito all'interno delle module.exports, non questo o esportazioni, più.

Un altro modo per farlo sarebbe:

math.js

module.exports.add = function (a, b) { 
    return a + b; 
}; 

O:

math.js

exports.add = function (a, b) { 
    return a + b; 
}; 
22

risposta di Renee è ben spiegato. Aggiunta alla risposta con un esempio:

Il nodo fa un sacco di cose al tuo file e uno dei più importanti è WRAPPING il tuo file. All'interno del codice sorgente nodejs viene restituito "module.exports". Facciamo un passo indietro e comprendiamo il wrapper. Supponiamo di avere

greet.js

var greet = function() { 
    console.log('Hello World'); 
}; 

module.exports = greet; 

il codice precedente è avvolto come IIFE (Subito Richiamato espressione di funzione) all'interno nodejs codice sorgente come segue:

(function (exports, require, module, __filename, __dirname) { //add by node 

     var greet = function() { 
     console.log('Hello World'); 
     }; 

     module.exports = greet; 

}).apply();             //add by node 

return module.exports;          //add by node 

e la suddetta funzione viene richiamata (.apply()) e restituito module.exports. In questo momento module.exports ed export puntano allo stesso riferimento.

Ora, immaginate di riscrivere greet.js come

exports = function() { 
    console.log('Hello World'); 
}; 
console.log(exports); 
console.log(module.exports); 

l'uscita sarà

[Function] 
{} 

il motivo è: module.exports è un oggetto vuoto. Non abbiamo impostato nulla su module.exports, piuttosto impostiamo exports = function() ..... in new greet.js. Quindi, module.exports è vuoto.

Tecnicamente le esportazioni e module.exports devono puntare allo stesso riferimento (è corretto !!). Ma usiamo "=" quando assegniamo function() .... alle esportazioni, che crea un altro oggetto nella memoria. Quindi, module.exports ed export producono risultati diversi. Quando si tratta di esportazioni, non possiamo ignorarlo.

Ora, immaginate di ri-scrittura (questo è chiamato Mutation) greet.js (riferendosi a Renee risposta) come

exports.a = function() { 
    console.log("Hello"); 
} 

console.log(exports); 
console.log(module.exports); 

l'uscita sarà

{ a: [Function] } 
{ a: [Function] } 

Come si può vedere module.exports ed export puntano allo stesso riferimento che è una funzione. Se imposti una proprietà sulle esportazioni, questa verrà impostata su module.exports perché in JS gli oggetti passano per riferimento.

Conclusione è sempre utilizzare module.exports per evitare confusione. Spero che questo aiuti. Felice codifica :)

Problemi correlati