NodeJS Tip: exports Vs module.exports

Danilo Del Fio
Sep 17, 2018 · 3 min read

Premessa

Prima di entrare nel topic dell’articolo è obbligatorio introdurre un concetto che renderà più chiaro quello di cui vorrei parlare.

Il concetto che sta alla base della gestione dei moduli e la loro utilizzazione tramite il comando require, è che ogni qual volta scriviamo un programma in node.js e lo eseguiamo, questo verrà “wrappato” all’interno di una definizione di funzione che ha la segiente firma:

(function (exports, require, module, __filename, __dirname) {
// nostro codice
});

La chiamata alla funzione avviene attraverso il fomato

fn(module.exports, require, module, filename, dirname);

Come si può vedere, la variabile exports che noi possiamo utilizzare all’interno dei nostri programmi, non è altro che una scosciatoia dell’attributo export dell’oggetto module che passiamo alla funzione come terzo parametro.

La figura precedente sottolinea come export non è nient’altro che un puntatore allo stesso oggetto referenziato da module.exports

Esempio

Creiamo un file exports.js e scriviamo:

exports = function() {
console.log('Prova shortcut export');
}
console.log(exports);
console.log(module.exports);

Se importiamo il file appena creato, in un nuovo file chiamato per esempio app.js, possiamo scrivere:

var exampleExports = require('./exports');
exampleExports();

se eseguiamo il comando node app.js otterremo come output:

E’ un risultato che può sembrare strano all’apparenza, perché prima ho detto che exports e module.exports puntano allo stesso oggetto.

In realtà, javascript crea un nuovo oggetto se si assegna un “valore” ad una variabile, quindi il risultato precedente viene ottenuto perché nell’esempio presentato module.exports ed exports puntano a due oggetti diversi.

L’errore visualizzato, inoltre, evidenzia un altro aspetto dell’export dei nostri moduli e del loro utilizzo in altri file attraverso l’uso del comando require(), infatti il comando specificato permette di importare tutto ciò che viene referenziato da module.exports ed essendo che nell’esempio precedente tale oggetto risulta vuoto

La funzione che pensavamo di avere esportato con exports non viene vista.

Mutations

Per poter ripristinare il comportamento atteso, dobbiamo, quindi fare in modo di non assegnare un valore alla variabile exports, facendo così in modo di “non rompere” il riferimento allo steso oggetto di module.exports.

Per fare ciò che ci proponiamo, basta utilizzare la cosiddetta “mutation”, ovvero non cambiamo il valore dell’oggetto, ma lo mutiamo.

Creiamo, per esempio, un file chiamato prova.js e scriviamo:

exports.esempioMutation = function() {
console.log('Esempio di Mutation');
}
console.log(exports);
console.log(module.exports);

Come si può vedere dal codice appena scritto, quindi, abbiamo creato un attributo all’interno dell’oggetto exports, in questo modo non avremmo rotto il legame tra exports e module.exports.

Supponiamo, quindi, di creare un altro file (per esempio chiamato prova-mutation.js), che ci permette di richiamare il codice appena scritto.

var prova = require('./prova');
prova.esempioMutation();

eseguendo il codice otteniamo, quindi:

Come possiamo vedere dall’output ottenuto, in questo caso non abbiamo rotto il legame tra i due oggetti e questo ci permette, quindi, di richiamare la funzione esportata ed ottenere il suo output che è semplicemente “Esempio di mutation”, cosa che prima non abbiamo potuto fare.

Conclusioni

Sebbene exports e module.exports puntino allo stesso oggetto, utilizzando la prima opzione potrebbe indurci ad ottenere dei comportamenti non previsti, quindi il mio consiglio è di utilizzare sempre module.exports per esportare le funzionalità che vogliamo mettere a dispposizione del nostro modulo, ma se desideriamo utilizzare esports è bene ricordarsi di usare la mutation, ovvero non assegnare direttamente un valore all’oggetto exports, ma ad un suo attributo.\

More From Medium

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade