module.exports vs exports dans Node.js

725

J'ai trouvé le contrat suivant dans un module Node.js:

module.exports = exports = nano = function database_module(cfg) {...}

Je me demande ce qui est la différence entre module.exportset exportspourquoi les deux sont utilisés ici.

Andreas Köberle
la source
81
Grande ressource: hacksparrow.com/node-js-exports-vs-module-exports.html ^ _ ^
Naftali aka Neal
6
Lien «pour la postérité» mis à jour: nodejs.org/docs/latest/api/modules.html#modules_module_exports
Zeke
8
Tout est question de références. Considérez les exportations comme un objet variable local pointant vers module.exports. Si vous remplacez la valeur des exportations, vous perdez la référence à module.exports et module.exports est ce que vous exposez en tant qu'interface publique.
Gabriel Llamas du
14
Résumé rapide: les deux exportset module.exportspointez sur le même objet, sauf si vous en réaffectez un. Et à la fin module.exportsest retourné. Donc, si vous avez réaffecté exportsune fonction, ne vous attendez pas à une fonction car elle ne sera pas renvoyée. Cependant, si vous aviez assigné une fonction comme celle-ci, la exports.func = function...chose résultante aurait une propriété func avec fonction comme valeur. Parce que vous avez ajouté la propriété à l'objet qui exportspointait ..
Muhammad Umer

Réponses:

426

Le réglage module.exportspermet database_moduled'appeler la fonction comme une fonction quand required. Un simple paramétrage exportsne permettrait pas d'exporter la fonction car le nœud exporte les module.exportsréférences des objets . Le code suivant ne permettrait pas à l'utilisateur d'appeler la fonction.

module.js

Ce qui suit ne fonctionnera pas.

exports = nano = function database_module(cfg) {return;}

Ce qui suit fonctionnera si module.exportsest défini.

module.exports = exports = nano = function database_module(cfg) {return;}

console

var func = require('./module.js');
// the following line will **work** with module.exports
func();

Fondamentalement, node.js n'exporte pas l'objet qui fait exportsactuellement référence, mais exporte les propriétés de ce exportsqui fait référence à l'origine. Bien que Node.js exporte les module.exportsréférences d' objet , vous permettant de l'appeler comme une fonction.


2e raison la moins importante

Ils définissent les deux module.exportset exportspour garantir qu'ils exportsne référencent pas l'objet précédemment exporté. En définissant les deux, vous les utilisez exportscomme raccourci et évitez les bugs potentiels plus tard.

L'utilisation exports.prop = true au lieu de module.exports.prop = truesauvegarde les caractères et évite la confusion.

Citron vert
la source
8
@ajostergaard: Il se trouve que c'est le nom de la bibliothèque dont l'exemple du PO a été tiré. Dans le module, il permet à l'auteur d'écrire des choses comme nano.version = '3.3'au lieu de module.exports.version = '3.3', ce qui se lit un peu plus clairement. (Notez qu'il nanos'agit d'une variable locale, déclarée un peu avant que les exportations de module ne soient définies .)
josh3736
3
@lime - merci - je suis content que ce soit en grande partie hors de propos car si ce n'était pas le cas, cela signifierait que j'ai tout mal compris. : - | :)
ostergaard
Hey Lime, c'est une réponse assez ancienne mais j'espère que vous pourrez clarifier quelque chose. Si je devais définir module.exportsmais pas exports , mon code fonctionnerait-il toujours? Merci pour toute aide!
Asad Saeeduddin
1
@Asad Oui, la fonction s'exportera correctement si vous la définissezmodule.exports
Lime
@Liam merci pour la précieuse réponse. quelques requêtes supplémentaires - à l'entrée de server.js, quelles devraient être les valeurs de module.exports et exports? module.exports devrait-il être nul et les exportations définies sur un objet vide? Est-ce hérité ou existe-t-il un cas d'utilisation valide pour pointer les exportations et module.exports vers deux objets différents?
Sushil
504

Même si la question a été répondue et acceptée il y a longtemps, je veux juste partager mes 2 cents:

Vous pouvez imaginer qu'au tout début de votre fichier, il y a quelque chose comme (juste pour explication):

var module = new Module(...);
var exports = module.exports;

entrez la description de l'image ici

Donc, quoi que vous fassiez, gardez à l'esprit cela module.exportset NON ne exportssera pas renvoyé de votre module lorsque vous aurez besoin de ce module ailleurs.

Donc, quand vous faites quelque chose comme:

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

Vous ajoutez 2 fonctions aet bà l'objet sur lequel des module.exportspoints aussi, donc le typeofrésultat de retour sera un object:{ a: [Function], b: [Function] }

Bien sûr, c'est le même résultat que vous obtiendrez si vous utilisez module.exportsdans cet exemple au lieu de exports.

C'est le cas où vous souhaitez que votre module.exportscomportement se fasse comme un conteneur de valeurs exportées. Alors que si vous voulez uniquement exporter une fonction constructeur, il y a quelque chose que vous devez savoir sur l'utilisation de module.exportsou exports; (rappelez-vous que module.exportscela sera retourné lorsque vous aurez besoin de quelque chose, pas export).

module.exports = function Something() {
    console.log('bla bla');
}

Maintenant, le typeofrésultat renvoyé est 'function'et vous pouvez l'exiger et invoquer immédiatement comme:
var x = require('./file1.js')();parce que vous écrasez le résultat renvoyé pour être une fonction.

Cependant, exportsvous ne pouvez pas utiliser quelque chose comme:

exports = function Something() {
    console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function

Parce qu'avec exports, la référence ne pointe plus vers l'objet où module.exportspointe, donc il n'y a plus de relation entre exportset module.exports. Dans ce cas, module.exportspointe toujours vers l'objet vide {}qui sera retourné.

La réponse acceptée d'un autre sujet devrait également aider: Javascript passe-t-il par référence?

Srle
la source
2
Belle explication mais je ne comprends toujours pas comment vous pouvez complètement omettre module.exportsun module, par exemple dans ce npmpaquet: github.com/tj/consolidate.js/blob/master/lib/consolidate.js
CodyBugstein
4
@Imray l'explication est ici: JavaScript passe-t-il par référence? exports.a = function(){}; works, exports = function(){} doesn't work
cirpo du
29
oooo enfin cette réponse l'explique. Fondamentalement, l'exportation fait référence à un objet auquel vous pouvez ajouter des propriétés, mais si vous le réaffectez pour fonctionner, vous n'attachez plus de propriété à cet objet d'origine. Maintenant, l'exportation fait référence à la fonction tandis que module.exports pointe toujours vers cet objet et puisque c'est ce qui est retourné. Vous pouvez dire que l'exportation a été essentiellement récupérée.
Muhammad Umer
5
Alors, quel est l'intérêt d'utiliser exports? Pourquoi ne pas toujours utiliser module.exportssi c'est juste une réaffectation de variable? Cela me semble déroutant.
jedd.ahyoung
1
@ jedd.ahyoung Il est moins lourd d'écrire à la exports.somethingplace demodule.exports.something
Srle
209

Fondamentalement, la réponse réside dans ce qui se passe réellement lorsqu'un module est requis via une requireinstruction. En supposant que c'est la première fois que le module est requis.

Par exemple:

var x = require('file1.js');

contenu de file1.js:

module.exports = '123';

Lorsque l'instruction ci-dessus est exécutée, un Moduleobjet est créé. Sa fonction constructeur est:

function Module(id, parent) {
    this.id = id;
    this.exports = {};
    this.parent = parent;
    if (parent && parent.children) {
        parent.children.push(this);
    }

    this.filename = null;
    this.loaded = false;
    this.children = [];
}

Comme vous le voyez, chaque objet module a une propriété avec un nom exports. C'est ce qui est finalement retourné dans le cadre de require.

La prochaine étape de require consiste à envelopper le contenu de file1.js dans une fonction anonyme comme ci-dessous:

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
});

Et cette fonction anonyme est invoquée de la manière suivante, modulese réfère ici à l' Moduleobjet créé précédemment.

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
}) (module.exports,require, module, "path_to_file1.js","directory of the file1.js");

Comme nous pouvons le voir à l'intérieur de la fonction, exportsl'argument formel fait référence à module.exports. En substance, c'est une commodité fournie au programmeur de modules.

Cependant, cette commodité doit être exercée avec soin. Dans tous les cas, si vous essayez d'affecter un nouvel objet aux exportations, assurez-vous de le faire de cette façon.

exports = module.exports = {};

Si nous le faisons dans le mauvais sens , module.exportsnous pointerons toujours vers l'objet créé dans le cadre de l'instance de module.

exports = {};

Par conséquent, l'ajout de quoi que ce soit à l'objet exports ci-dessus n'aura aucun effet sur l'objet module.exports et rien ne sera exporté ou retourné dans le cadre de require.

Chandu
la source
8
Perdu moi iciexports = module.exports = {};
Giant Elk
2
Je pense que cela devrait être la meilleure réponse, cela explique pourquoi func()échoue dans la réponse de @ William!
tourterelle
2
Je ne vois aucun avantage à ajouter exports = module.exports = app;à la dernière ligne du code. Il semble que le module.exportssera exporté et que nous n'utiliserons jamais exports, car encore une fois, c'est à la dernière ligne du code. Alors, pourquoi ne pas simplement ajoutermodule.exports = app;
lvarayut
79

Initialement, module.exports=exportset la requirefonction renvoie l'objet module.exportsauquel il se réfère.

si nous ajoutons une propriété à l'objet, disons exports.a=1, alors module.exports et exports font toujours référence au même objet. Donc, si nous appelons require et assignons le module à une variable, alors la variable a une propriété a et sa valeur est 1;

Mais si nous remplaçons l' un d'eux, par exemple, exports=function(){}alors ils sont différents maintenant: les exportations se réfèrent à un nouvel objet et module.exports se réfèrent à l'objet d'origine. Et si nous avons besoin du fichier, il ne renverra pas le nouvel objet, car module.exports ne fait pas référence au nouvel objet.

Pour moi, je continuerai d'ajouter de nouvelles propriétés ou de les remplacer toutes les deux par un nouvel objet. Ignorer un n'est pas juste. Et gardez à l'esprit que module.exportsc'est le vrai patron.

Cameron
la source
1
Ouais, c'est en fait la vraie réponse. C'est concis et clair. D'autres peuvent avoir raison mais sont pleins de termes fantaisistes et ne se concentrent pas exactement sur la réponse à cette question.
Khoa
C'est de loin la réponse la plus claire! Dans le cas où vous souhaitez le mettre en signet, c'est le lien précis: stackoverflow.com/questions/7137397/…
lambdarookie
56

exportset module.exportssont les mêmes, sauf si vous réaffectez exportsdans votre module.

La façon la plus simple d'y penser est de penser que cette ligne est implicitement en haut de chaque module.

var exports = module.exports = {};

Si, dans votre module, vous réaffectez exports, vous le réaffectez dans votre module et il n'est plus égal module.exports. C'est pourquoi, si vous souhaitez exporter une fonction, vous devez faire:

module.exports = function() { ... }

Si vous avez simplement assigné votre function() { ... }à exports, vous seriez réattribué exportspour ne plus pointer vers module.exports.

Si vous ne voulez pas vous référer à votre fonction à module.exportschaque fois, vous pouvez faire:

module.exports = exports = function() { ... }

Notez que module.exportsc'est l'argument le plus à gauche.

Attacher des propriétés à exportsn'est pas le même puisque vous ne le réaffectez pas. Voilà pourquoi cela fonctionne

exports.foo = function() { ... }
dustin.schultz
la source
9
C'était la plus facile à comprendre parmi toutes les réponses!
Adarsh ​​Konchady
2
Nice and straightforward
fibono
1
Un moyen simple et plus facile de comprendre cette fonctionnalité.
FilipeCanatto
27

JavaScript passe des objets par copie d'une référence

C'est une différence subtile à voir avec la façon dont les objets sont passés par référence en JavaScript.

exportset les module.exportsdeux pointent vers le même objet. exportsest une variable et module.exportsest un attribut de l'objet module.

Dis que j'écris quelque chose comme ça:

exports = {a:1};
module.exports = {b:12};

exportset module.exportspointez maintenant sur différents objets. La modification des exportations ne modifie plus module.exports.

Lorsque la fonction d'importation inspecte, module.exportselle obtient{b:12}

superluminaire
la source
6
Meilleure réponse à mon humble avis!
M. AJ
1
"JavaScript passe par référence" - Non.
xehpuk
13

Je fais juste un test, il s'avère que, dans le code du module de nodejs, il devrait ressembler à ceci:

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

donc:

1:

exports = function(){}; // this will not work! as it make the exports to some other pointer
module.exports = function(){}; // it works! cause finally nodejs make the module.exports to export.

2:

exports.abc = function(){}; // works!
exports.efg = function(){}; // works!

3: mais, alors que dans ce cas

module.exports = function(){}; // from now on we have to using module.exports to attach more stuff to exports.
module.exports.a = 'value a'; // works
exports.b = 'value b'; // the b will nerver be seen cause of the first line of code we have do it before (or later)
Lyman Lai
la source
Lyman, module.exportsest donc en quelque sorte la `` vraie affaire '' dont le nœud sort, mais à un moment donné, vous devrez ajouter tout votre contenu exportsà module.exportsmoins que vous n'utilisiez un exports.namespace(cas 2 ci-dessus), qui dans ce cas semble être comme Le nœud a exécuté un extends(module.exports, exports);ajout de tous les «espaces de noms» exportsà l' module.exportsobjet? En d'autres termes, si vous utilisez, exportsvous souhaitez probablement y définir des propriétés?
Cody
11

Voici une bonne description écrite sur les modules de nœuds dans node.js dans le livre d' actions de la publication Manning .
Ce qui est finalement exporté dans votre application est module.exports.
exports
est configuré simplement comme une référence globale à module.exports , qui est initialement défini comme un objet vide auquel vous pouvez ajouter des propriétés. Donc exports.myFunc n'est qu'un raccourci pour module.exports.myFunc .

Par conséquent, si exports est défini sur autre chose, il rompt la référence entre module.exports et exports . Parce que module.exportsest ce qui est réellement exporté, les exportations ne fonctionneront plus comme prévu - il ne fait plus référence au module .exports . Si vous souhaitez conserver ce lien, vous pouvez de nouveau effectuer des exportations de référence module.exports comme suit:

module.exports = exports = db;
Salar
la source
8

J'ai fait quelques tests et je pense que cela peut éclairer le sujet ...

app.js:

var ...
  , routes = require('./routes')
  ...;
...
console.log('@routes', routes);
...

versions de /routes/index.js:

exports = function fn(){}; // outputs "@routes {}"

exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

module.exports = function fn(){};  // outputs "@routes function fn(){}"

module.exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

J'ai même ajouté de nouveaux fichiers:

./routes/index.js:

module.exports = require('./not-index.js');
module.exports = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

Nous obtenons la sortie "@routes {}"


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

Nous obtenons la sortie "@routes {fn: {}, utilisateur: {}}"


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.user = function user(){};

Nous obtenons la sortie "@routes {user: [Fonction: utilisateur]}" Si nous passons user.jsà { ThisLoadedLast: [Function: ThisLoadedLast] }, nous obtenons la sortie "@routes {ThisLoadedLast: [Fonction: ThisLoadedLast]}".


Mais si on modifie ./routes/index.js...

./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.ThisLoadedLast = function ThisLoadedLast(){};

... nous obtenons "@routes {fn: {fn: [Fonction: fn]}, ThisLoadedLast: {ThisLoadedLast: [Fonction: ThisLoadedLast]}}" "

Je suggère donc de toujours utiliser module.exportsdans vos définitions de module.

Je ne comprends pas complètement ce qui se passe en interne avec Node, mais veuillez commenter si vous pouvez donner plus de sens à cela, car je suis sûr que cela aide.

- Codage heureux

Cody
la source
Je pense qu'ils sont inutilement compliqués et déroutants. Il doit être transparent et intuitif.
ngungo
Je suis d'accord. Cela peut être utile pour l'espacement de noms dans certaines circonstances, mais ne va généralement pas faire ou casser quoi que ce soit.
Cody
4

Cela montre comment require()fonctionne sous sa forme la plus simple, extrait de Eloquent JavaScript

Problème Il n'est pas possible pour un module d'exporter directement une valeur autre que l'objet exports, telle qu'une fonction. Par exemple, un module peut vouloir exporter uniquement le constructeur du type d'objet qu'il définit. Pour l'instant, il ne peut pas le faire car require utilise toujours l' exportsobjet qu'il crée comme valeur exportée.

Solution Fournissez aux modules une autre variable, modulequi est un objet possédant une propriété exports. Cette propriété pointe initialement sur l'objet vide créé par require mais peut être remplacé par une autre valeur afin d'exporter autre chose.

function require(name) {
  if (name in require.cache)
    return require.cache[name];
  var code = new Function("exports, module", readFile(name));
  var exports = {}, module = {exports: exports};
  code(exports, module);
  require.cache[name] = module.exports;
  return module.exports;
}
require.cache = Object.create(null);
onmyway133
la source
J'ai dû recréer cela dans Node et tester quelques choses jusqu'à ce que je sois, je suis nul. Fondamentalement, la fonction interne créée pour le module ne renvoie même jamais l'objet exports. Ainsi, l'objet "exports" n'est pas réellement réaffecté dans le module, par exemple si vous essayez d'écrire exports = "c'est maintenant une chaîne" directement. L'objet n'existe que comme référence. C'est un comportement que je ne pense pas avoir vraiment bien compris jusqu'à présent.
danielgormly
4

Voici le résultat de

console.log("module:");
console.log(module);

console.log("exports:");
console.log(exports);

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

entrez la description de l'image ici

Aussi:

if(module.exports === exports){
    console.log("YES");
}else{
    console.log("NO");
}

//YES

Remarque: La spécification CommonJS autorise uniquement l'utilisation de la variable exports pour exposer les membres publics. Par conséquent, le modèle d'export nommé est le seul qui soit vraiment compatible avec la spécification CommonJS. L'utilisation de module.exports est une extension fournie par Node.js pour prendre en charge une plus large gamme de modèles de définition de module.

serkan
la source
4
var a = {},md={};

// Premièrement, les exports et module.exports pointent le même objet vide

exp = a;//exports =a;
md.exp = a;//module.exports = a;

exp.attr = "change";

console.log(md.exp);//{attr:"change"}

// Si vous pointez exp vers un autre objet au lieu de pointer c'est la propriété d'un autre objet. Le md.exp sera un objet vide {}

var a ={},md={};
exp =a;
md.exp =a;

exp = function(){ console.log('Do nothing...'); };

console.log(md.exp); //{}
Anson Hwang
la source
4

À partir des documents

La variable exports est disponible dans la portée de niveau fichier d'un module et se voit attribuer la valeur de module.exports avant l'évaluation du module.

Il permet un raccourci, de sorte que module.exports.f = ... peut être écrit plus succinctement comme exports.f = .... Cependant, sachez que comme toute variable, si une nouvelle valeur est affectée aux exportations, elle est n'est plus lié à module.exports:

Il s'agit simplement d'une variable pointant vers module.exports.

ANewGuyInTown
la source
4

J'ai trouvé ce lien utile pour répondre à la question ci-dessus.

http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/

Pour ajouter aux autres messages Le système de modules dans le nœud ne

var exports = module.exports 

avant d'exécuter votre code. Donc, quand vous voulez exporter = foo, vous voulez probablement faire module.exports = exports = foo mais utiliser exports.foo = foo devrait être bien

Sudhir Srinivasan
la source
git link is broken
Jesse Hattabaugh
Le lien est maintenant corrigé.
Paweł Gościcki
3

"Si vous souhaitez que la racine de l'exportation de votre module soit une fonction (telle qu'un constructeur) ou si vous souhaitez exporter un objet complet dans une affectation au lieu de le créer une propriété à la fois, affectez-le à module.exports au lieu de exportations." - http://nodejs.org/api/modules.html

madKakoo
la source
3

module.exportset les exportsdeux pointent vers le même objet avant l'évaluation du module.

Toute propriété que vous ajoutez à l' module.exports objet sera disponible lorsque votre module sera utilisé dans un autre module using requirestatement. exportsest un raccourci mis à disposition pour la même chose. Par exemple:

module.exports.add = (a, b) => a+b

équivaut à écrire:

exports.add = (a, b) => a+b

Donc, c'est correct tant que vous n'affectez pas de nouvelle valeur à la exportsvariable. Lorsque vous faites quelque chose comme ça:

exports = (a, b) => a+b 

car vous lui affectez une nouvelle valeur exportsn'a plus de référence à l'objet exporté et restera donc local à votre module.

Si vous prévoyez d'attribuer une nouvelle valeur à module.exportsplutôt que d'ajouter de nouvelles propriétés à l'objet initial rendu disponible, vous devriez probablement envisager de faire comme indiqué ci-dessous:

module.exports = exports = (a, b) => a+b

Le site Web Node.js a une très bonne explication à ce sujet.

Justin Pathrose Vareed
la source
2

1. exportations -> utilisation comme utilitaire singleton
2. module-exports -> utilisation comme objets logiques tels que service, modèle, etc.

riv
la source
2

Créons un module de 2 façons:

Une manière

var aa = {
    a: () => {return 'a'},
    b: () => {return 'b'}
}

module.exports = aa;

Deuxième voie

exports.a = () => {return 'a';}
exports.b = () => {return 'b';}

Et c'est ainsi que require () intégrera le module.

Première voie:

function require(){
    module.exports = {};
    var exports = module.exports;

    var aa = {
        a: () => {return 'a'},
        b: () => {return 'b'}
    }
    module.exports = aa;

    return module.exports;
}

Deuxième voie

function require(){
    module.exports = {};
    var exports = module.exports;

    exports.a = () => {return 'a';}
    exports.b = () => {return 'b';}

    return module.exports;
}
Dmitry Sergeev
la source
2

pourquoi les deux sont utilisés ici

Je crois qu'ils veulent juste être clair que module.exports, exportset le nanopoint à la même fonction - vous permettant d'utiliser soit variable pour appeler la fonction dans le fichier. nanofournit un contexte à ce que fait la fonction.

exportsne sera pas exporté (seulement module.exports), alors pourquoi s'embêter aussi?

Le compromis de verbosité limite le risque de futurs bogues, comme l'utilisation exportsau lieu du module.exportsfichier. Il apporte également des précisions à ce sujet module.exportset exportsindique en fait la même valeur.


module.exports contre exports

Tant que vous ne réaffectez pas module.exportsou exports(et ajoutez plutôt des valeurs à l'objet auquel ils se réfèrent tous les deux), vous n'aurez aucun problème et pourrez utiliser en toute sécurité exportspour être plus concis.

Lorsqu'ils sont attribués à un non-objet, ils pointent désormais vers des endroits différents qui peuvent prêter à confusion, sauf si vous voulez intentionnellement module.exportsêtre quelque chose de spécifique (comme une fonction).

La définition exportsd'un non-objet n'a pas beaucoup de sens car vous devrez le définir module.exports = exportsà la fin pour pouvoir l'utiliser dans d'autres fichiers.

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

exports.msg = 'hi';
console.log(module.exports === exports); // true

exports = 'yo';
console.log(module.exports === exports); // false

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

module.exports = 'hello';
console.log(module.exports === exports); // false

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

Pourquoi attribuer module.exportsà une fonction?

Plus concis! Comparez combien le deuxième exemple est plus court:

helloWorld1.js: module.exports.hello = () => console.log('hello world');

app1.js: let sayHello = require('./helloWorld1'); sayHello.hello; // hello world

helloWorld2.js: module.exports = () => console.log('hello world');

app2.js: let sayHello = require('./helloWorld2'); sayHello; // hello world

JBallin
la source
2

entrez la description de l'image ici

Chaque fichier que vous créez est un module. module est un objet. Il a une propriété appelée exports : {}qui est un objet vide par défaut.

vous pouvez créer des fonctions / intergiciels et ajouter à cette exportation vide un objet tel exports.findById() => { ... } alors requirene importe où dans votre application et l' utilisation ...

controllers / user.js

exports.findById = () => {
    //  do something
}

nécessite dans routes.js d'utiliser:

const {findyId} = './controllers/user'
Ryan Dhungel
la source
2

Pour comprendre les différences, vous devez d'abord comprendre ce que Node.js fait à chaque module pendant l'exécution. Node.js crée une fonction wrapper pour chaque module:

 (function(exports, require, module, __filename, __dirname) {

 })()

Notez que le premier paramètre exportsest un objet vide, et le troisième paramètre moduleest un objet avec de nombreuses propriétés, et l'une des propriétés est nommée exports. C'est ce qui exportsvient et ce qui module.exportsvient. Le premier est un objet variable et le dernier est une propriété d' moduleobjet.

Dans le module, Node.js fait automatiquement cette chose au début :,module.exports = exports et revient finalement module.exports.

Vous pouvez donc voir que si vous réaffectez une valeur à exports, cela n'aura aucun effet module.exports. (Tout simplement parce qu'il exportspointe vers un autre nouvel objet, mais module.exportscontient toujours l'ancien exports)

let exports = {};
const module = {};
module.exports = exports;

exports = { a: 1 }
console.log(module.exports) // {}

Mais si vous mettez à jour les propriétés de exports, cela aura sûrement un effet sur module.exports. Parce qu'ils pointent tous les deux vers le même objet.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports.b = 2;
console.log(module.exports) // { a: 1, b: 2 }

Notez également que si vous réaffectez une autre valeur à module.exports, cela semble inutile pour les exportsmises à jour. Chaque mise à jour exportsest ignorée car module.exportspointe vers un autre objet.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports = {
  hello: () => console.log('hello')
}
console.log(module.exports) // { hello: () => console.log('hello')}
qinmu2127
la source
0

dans le fichier node js module.js est utilisé pour exécuter l'heure module.load system.every lorsque le nœud exécute un fichier, il enveloppe le contenu de votre fichier js comme suit

'(function (exports, require, module, __filename, __dirname) {',+
     //your js file content
 '\n});'

en raison de cet encapsulation dans le code source ur js, vous pouvez accéder aux exportations, exiger, module, etc.

puis le nœud exécute cette fonction encapsulée à l'aide de c ++. à ce moment, les objets exportés qui sont passés dans cette fonction seront remplis.

vous pouvez voir à l'intérieur de cette fonction les exportations et le module des paramètres. en fait, les exportations sont un membre public de la fonction constructeur du module.

regardez le code suivant

copiez ce code dans b.js

console.log("module is "+Object.prototype.toString.call(module));
console.log("object.keys "+Object.keys(module));
console.log(module.exports);
console.log(exports === module.exports);
console.log("exports is "+Object.prototype.toString.call(exports));
console.log('----------------------------------------------');
var foo = require('a.js');
console.log("object.keys of foo: "+Object.keys(foo));
console.log('name is '+ foo);
foo();

copiez ce code dans a.js

exports.name = 'hello';
module.exports.name = 'hi';
module.exports.age = 23;
module.exports = function(){console.log('function to module exports')};
//exports = function(){console.log('function to export');}

maintenant exécuté en utilisant le nœud

c'est la sortie

module is [object Object]
object.keys id,exports,parent,filename,loaded,children,paths
{}
true

les exportations sont [objet Object]

object.keys of foo: le nom est function () {console.log ('fonction vers module exporte')} fonction vers module exporte

supprimez maintenant la ligne commentée dans a.js et commentez la ligne au-dessus de cette ligne et supprimez la dernière ligne de b.js et exécutez.

dans le monde javascript, vous ne pouvez pas réaffecter un objet passé en paramètre, mais vous pouvez changer le membre public de la fonction lorsque l'objet de cette fonction est défini comme paramètre sur une autre fonction

se souvient

utilisez module.exports sur et uniquement si vous souhaitez obtenir une fonction lorsque vous utilisez le mot clé require. dans l'exemple ci-dessus, nous varons foo = require (a.js); vous pouvez voir que nous pouvons appeler foo en tant que fonction;

c'est ainsi que la documentation du nœud l'explique "L'objet exports est créé par le système Module. Parfois, cela n'est pas acceptable, beaucoup veulent que leur module soit une instance d'une classe. Pour ce faire, affectez l'objet d'exportation souhaité à module.exports."

sidias
la source
0
  1. Les deux module.exportset exportsindiquent la même chose function database_module(cfg) {...}.

    1| var a, b;
    2| a = b = function() { console.log("Old"); };
    3|     b = function() { console.log("New"); };
    4|
    5| a(); // "Old"
    6| b(); // "New"

    Vous pouvez changer bsur la ligne 3 en a, la sortie est inversée. La conclusion est:

    aet bsont indépendants.

  2. module.exports = exports = nano = function database_module(cfg) {...}Est donc équivalent à:

    var f = function database_module(cfg) {...};
    module.exports = f;
    exports = f;

    Supposons que ce qui précède module.jsest requis par foo.js. Les avantages de module.exports = exports = nano = function database_module(cfg) {...}est clair maintenant:

    • Dans foo.js, puisque module.exportsc'est require('./module.js'):

      var output = require('./modules.js')();
    • Dans moduls.js: vous pouvez utiliser à la exportsplace de module.exports.

Alors, vous serez heureux si les deux exportset module.exportspointant vers la même chose.

Il pleut
la source