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.exports
et exports
pourquoi les deux sont utilisés ici.
javascript
node.js
commonjs
Andreas Köberle
la source
la source
exports
etmodule.exports
pointez sur le même objet, sauf si vous en réaffectez un. Et à la finmodule.exports
est retourné. Donc, si vous avez réaffectéexports
une fonction, ne vous attendez pas à une fonction car elle ne sera pas renvoyée. Cependant, si vous aviez assigné une fonction comme celle-ci, laexports.func = function...
chose résultante aurait une propriété func avec fonction comme valeur. Parce que vous avez ajouté la propriété à l'objet quiexports
pointait ..Réponses:
Le réglage
module.exports
permetdatabase_module
d'appeler la fonction comme une fonction quandrequired
. Un simple paramétrageexports
ne permettrait pas d'exporter la fonction car le nœud exporte lesmodule.exports
références des objets . Le code suivant ne permettrait pas à l'utilisateur d'appeler la fonction.module.js
Ce qui suit ne fonctionnera pas.
Ce qui suit fonctionnera si
module.exports
est défini.console
Fondamentalement, node.js n'exporte pas l'objet qui fait
exports
actuellement référence, mais exporte les propriétés de ceexports
qui fait référence à l'origine. Bien que Node.js exporte lesmodule.exports
références d' objet , vous permettant de l'appeler comme une fonction.2e raison la moins importante
Ils définissent les deux
module.exports
etexports
pour garantir qu'ilsexports
ne référencent pas l'objet précédemment exporté. En définissant les deux, vous les utilisezexports
comme raccourci et évitez les bugs potentiels plus tard.L'utilisation
exports.prop = true
au lieu demodule.exports.prop = true
sauvegarde les caractères et évite la confusion.la source
nano.version = '3.3'
au lieu demodule.exports.version = '3.3'
, ce qui se lit un peu plus clairement. (Notez qu'ilnano
s'agit d'une variable locale, déclarée un peu avant que les exportations de module ne soient définies .)module.exports
mais pasexports
, mon code fonctionnerait-il toujours? Merci pour toute aide!module.exports
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):
Donc, quoi que vous fassiez, gardez à l'esprit cela
module.exports
et NON neexports
sera pas renvoyé de votre module lorsque vous aurez besoin de ce module ailleurs.Donc, quand vous faites quelque chose comme:
Vous ajoutez 2 fonctions
a
etb
à l'objet sur lequel desmodule.exports
points aussi, donc letypeof
résultat de retour sera unobject
:{ a: [Function], b: [Function] }
Bien sûr, c'est le même résultat que vous obtiendrez si vous utilisez
module.exports
dans cet exemple au lieu deexports
.C'est le cas où vous souhaitez que votre
module.exports
comportement 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 demodule.exports
ouexports
; (rappelez-vous quemodule.exports
cela sera retourné lorsque vous aurez besoin de quelque chose, pasexport
).Maintenant, le
typeof
ré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,
exports
vous ne pouvez pas utiliser quelque chose comme:Parce qu'avec
exports
, la référence ne pointe plus vers l'objet oùmodule.exports
pointe, donc il n'y a plus de relation entreexports
etmodule.exports
. Dans ce cas,module.exports
pointe 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?
la source
module.exports
un module, par exemple dans cenpm
paquet: github.com/tj/consolidate.js/blob/master/lib/consolidate.jsexports.a = function(){}; works, exports = function(){} doesn't work
exports
? Pourquoi ne pas toujours utilisermodule.exports
si c'est juste une réaffectation de variable? Cela me semble déroutant.exports.something
place demodule.exports.something
Fondamentalement, la réponse réside dans ce qui se passe réellement lorsqu'un module est requis via une
require
instruction. En supposant que c'est la première fois que le module est requis.Par exemple:
contenu de file1.js:
Lorsque l'instruction ci-dessus est exécutée, un
Module
objet est créé. Sa fonction constructeur est: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 derequire
.La prochaine étape de require consiste à envelopper le contenu de file1.js dans une fonction anonyme comme ci-dessous:
Et cette fonction anonyme est invoquée de la manière suivante,
module
se réfère ici à l'Module
objet créé précédemment.Comme nous pouvons le voir à l'intérieur de la fonction,
exports
l'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.
Si nous le faisons dans le mauvais sens ,
module.exports
nous pointerons toujours vers l'objet créé dans le cadre de l'instance de module.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.
la source
exports = module.exports = {};
func()
échoue dans la réponse de @ William!exports = module.exports = app;
à la dernière ligne du code. Il semble que lemodule.exports
sera exporté et que nous n'utiliserons jamaisexports
, car encore une fois, c'est à la dernière ligne du code. Alors, pourquoi ne pas simplement ajoutermodule.exports = app;
Initialement,
module.exports=exports
et larequire
fonction renvoie l'objetmodule.exports
auquel 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.exports
c'est le vrai patron.la source
exports
etmodule.exports
sont les mêmes, sauf si vous réaffectezexports
dans votre module.La façon la plus simple d'y penser est de penser que cette ligne est implicitement en haut de chaque module.
Si, dans votre module, vous réaffectez
exports
, vous le réaffectez dans votre module et il n'est plus égalmodule.exports
. C'est pourquoi, si vous souhaitez exporter une fonction, vous devez faire:Si vous avez simplement assigné votre
function() { ... }
àexports
, vous seriez réattribuéexports
pour ne plus pointer versmodule.exports
.Si vous ne voulez pas vous référer à votre fonction à
module.exports
chaque fois, vous pouvez faire:Notez que
module.exports
c'est l'argument le plus à gauche.Attacher des propriétés à
exports
n'est pas le même puisque vous ne le réaffectez pas. Voilà pourquoi cela fonctionnela source
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.
exports
et lesmodule.exports
deux pointent vers le même objet.exports
est une variable etmodule.exports
est un attribut de l'objet module.Dis que j'écris quelque chose comme ça:
exports
etmodule.exports
pointez maintenant sur différents objets. La modification des exportations ne modifie plus module.exports.Lorsque la fonction d'importation inspecte,
module.exports
elle obtient{b:12}
la source
Je fais juste un test, il s'avère que, dans le code du module de nodejs, il devrait ressembler à ceci:
donc:
1:
2:
3: mais, alors que dans ce cas
la source
module.exports
est donc en quelque sorte la `` vraie affaire '' dont le nœud sort, mais à un moment donné, vous devrez ajouter tout votre contenuexports
àmodule.exports
moins que vous n'utilisiez unexports.namespace
(cas 2 ci-dessus), qui dans ce cas semble être comme Le nœud a exécuté unextends(module.exports, exports);
ajout de tous les «espaces de noms»exports
à l'module.exports
objet? En d'autres termes, si vous utilisez,exports
vous souhaitez probablement y définir des propriétés?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:
la source
J'ai fait quelques tests et je pense que cela peut éclairer le sujet ...
app.js
:versions de
/routes/index.js
:J'ai même ajouté de nouveaux fichiers:
./routes/index.js
:./routes/not-index.js
:./routes/user.js
:Nous obtenons la sortie "@routes {}"
./routes/index.js
:./routes/not-index.js
:./routes/user.js
:Nous obtenons la sortie "@routes {fn: {}, utilisateur: {}}"
./routes/index.js
:./routes/not-index.js
:./routes/user.js
: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
:./routes/not-index.js
:./routes/user.js
:... nous obtenons "@routes {fn: {fn: [Fonction: fn]}, ThisLoadedLast: {ThisLoadedLast: [Fonction: ThisLoadedLast]}}" "
Je suggère donc de toujours utiliser
module.exports
dans 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
la source
Cela montre comment
require()
fonctionne sous sa forme la plus simple, extrait de Eloquent JavaScriptProblè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'
exports
objet qu'il crée comme valeur exportée.Solution Fournissez aux modules une autre variable,
module
qui 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.la source
Voici le résultat de
Aussi:
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.
la source
// Premièrement, les exports et module.exports pointent le même objet vide
// 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 {}
la source
À partir des documents
Il s'agit simplement d'une variable pointant vers module.exports.
la source
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
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
la source
"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
la source
module.exports
et lesexports
deux 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 usingrequire
statement.exports
est un raccourci mis à disposition pour la même chose. Par exemple:équivaut à écrire:
Donc, c'est correct tant que vous n'affectez pas de nouvelle valeur à la
exports
variable. Lorsque vous faites quelque chose comme ça:car vous lui affectez une nouvelle valeur
exports
n'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.exports
plutôt que d'ajouter de nouvelles propriétés à l'objet initial rendu disponible, vous devriez probablement envisager de faire comme indiqué ci-dessous:Le site Web Node.js a une très bonne explication à ce sujet.
la source
1. exportations -> utilisation comme utilitaire singleton
2. module-exports -> utilisation comme objets logiques tels que service, modèle, etc.
la source
Créons un module de 2 façons:
Une manière
Deuxième voie
Et c'est ainsi que require () intégrera le module.
Première voie:
Deuxième voie
la source
Je crois qu'ils veulent juste être clair que
module.exports
,exports
et lenano
point à la même fonction - vous permettant d'utiliser soit variable pour appeler la fonction dans le fichier.nano
fournit un contexte à ce que fait la fonction.exports
ne sera pas exporté (seulementmodule.exports
), alors pourquoi s'embêter aussi?Le compromis de verbosité limite le risque de futurs bogues, comme l'utilisation
exports
au lieu dumodule.exports
fichier. Il apporte également des précisions à ce sujetmodule.exports
etexports
indique en fait la même valeur.module.exports
contreexports
Tant que vous ne réaffectez pas
module.exports
ouexports
(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éexports
pour ê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
exports
d'un non-objet n'a pas beaucoup de sens car vous devrez le définirmodule.exports = exports
à la fin pour pouvoir l'utiliser dans d'autres fichiers.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:
helloWorld2.js:let sayHello = require('./helloWorld1'); sayHello.hello; // hello world
module.exports = () => console.log('hello world');
app2.js:
let sayHello = require('./helloWorld2'); sayHello; // hello world
la source
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() => { ... }
alorsrequire
ne importe où dans votre application et l' utilisation ...controllers / user.js
nécessite dans routes.js d'utiliser:
la source
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:
Notez que le premier paramètre
exports
est un objet vide, et le troisième paramètremodule
est un objet avec de nombreuses propriétés, et l'une des propriétés est nomméeexports
. C'est ce quiexports
vient et ce quimodule.exports
vient. Le premier est un objet variable et le dernier est une propriété d'module
objet.Dans le module, Node.js fait automatiquement cette chose au début :,
module.exports = exports
et revient finalementmodule.exports
.Vous pouvez donc voir que si vous réaffectez une valeur à
exports
, cela n'aura aucun effetmodule.exports
. (Tout simplement parce qu'ilexports
pointe vers un autre nouvel objet, maismodule.exports
contient toujours l'ancienexports
)Mais si vous mettez à jour les propriétés de
exports
, cela aura sûrement un effet surmodule.exports
. Parce qu'ils pointent tous les deux vers le même objet.Notez également que si vous réaffectez une autre valeur à
module.exports
, cela semble inutile pour lesexports
mises à jour. Chaque mise à jourexports
est ignorée carmodule.exports
pointe vers un autre objet.la source
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
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
copiez ce code dans a.js
maintenant exécuté en utilisant le nœud
c'est la sortie
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."
la source
Vous pouvez changer
b
sur la ligne 3 ena
, la sortie est inversée. La conclusion est:module.exports = exports = nano = function database_module(cfg) {...}
Est donc équivalent à:Supposons que ce qui précède
module.js
est requis parfoo.js
. Les avantages demodule.exports = exports = nano = function database_module(cfg) {...}
est clair maintenant:Dans
foo.js
, puisquemodule.exports
c'estrequire('./module.js')
:Dans
moduls.js
: vous pouvez utiliser à laexports
place demodule.exports
.Alors, vous serez heureux si les deux
exports
etmodule.exports
pointant vers la même chose.la source