Question module.exports vs exportations dans Node.js


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

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

Je me demande quel est le différent entre module.exports et exports et pourquoi les deux sont utilisés ici.


608
2017-08-21 09:16


origine


Réponses:


Réglage module.exports permet le database_module fonction à appeler comme une fonction quand required. Réglage simple exports ne permettrait pas que la fonction soit exporté car le noeud exporte l'objet module.exports les références. 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.exports est réglé.

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 exports actuellement des références, mais exporte les propriétés de exports références à l'origine. Bien que Node.js exporte l'objet module.exports références, vous permettant de l'appeler comme une fonction.


2ème raison la moins importante

Ils ont mis les deux module.exports et exports s'assurer exports ne fait pas référence à l'objet exporté antérieur. En définissant les deux vous utilisez exports comme un raccourci et éviter les bugs potentiels plus tard sur la route.

En utilisant exports.prop = true  au lieu de module.exports.prop = true enregistre les caractères et évite la confusion.


373
2017-08-22 03:38



Même si la question a été répondue et acceptée depuis 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 l'explication):

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

enter image description here

Donc, quoi que vous fassiez, gardez à l'esprit que module.exports et pas exports sera renvoyé par 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 'a' et 'b' à l'objet sur lequel module.exports pointe aussi, ainsi le typeof le résultat du 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.exports dans cet exemple au lieu de exports.

C'est le cas où vous voulez que votre module.exports se comporte comme un conteneur de valeurs exportées. Considérant que, si vous voulez seulement exporter une fonction constructeur, il y a quelque chose que vous devriez savoir sur l'utilisation module.exports ou exports; (Rappelez-vous encore que module.exports sera retourné quand vous avez besoin de quelque chose, pas d'exportation).

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

Maintenant, typeof renvoie le résultat 'function' et vous pouvez l'exiger et invoquer immédiatement comme:
  var x = require('./file1.js')(); car vous remplacez le résultat renvoyé par une fonction.

Cependant, en utilisant exports vous 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.exports points, donc il n'y a pas de relation entre exports et module.exports plus. Dans ce cas, module.exports pointe toujours sur l'objet vide {} qui sera retourné.

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


373
2017-10-19 15:07



Fondamentalement, la réponse réside dans ce qui se passe réellement lorsqu'un module est requis via require déclaration. 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 Module l'objet est créé. Sa fonction de 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 voyez chaque objet de module a une propriété avec le nom exports. C'est ce qui est finalement retourné dans le cadre de require.

La prochaine étape de require est d'enrouler 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, module ici se réfère à la Module Objet 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 on peut le voir à l'intérieur de la fonction, exports argument formel se réfère à module.exports. En substance, c'est une commodité fournie au programmeur de module.

Cependant, cette commodité doit être exercée avec précaution. Dans tous les cas, si vous essayez d'assigner un nouvel objet à exporter, assurez-vous de le faire de cette façon.

exports = module.exports = {};

Si nous le faisons de la manière suivante Fausse Route, module.exports pointera toujours sur l'objet créé dans le cadre de l'instance de module.

exports = {};

En conséquence, l'ajout de n'importe quoi à l'objet d'exportation ci-dessus n'aura aucun effet sur l'objet module.exports et rien ne sera exporté ou retourné dans le cadre de require.


191
2017-07-30 10:24



Initialement,module.exports=exports , et le require La fonction retourne l'objet module.exports fait référence à.

si nous ajouter une propriété à l'objet, disons exports.a=1, puis module.exports et exports encore se référer 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 passer outre l'un d'eux, par exemple, exports=function(){}alors ils sont différent maintenant: exports fait référence à un nouvel objet et module.exports fait référence à l'objet d'origine. Et si nous avons besoin du fichier, il ne retournera pas le nouvel objet, puisque module.exports ne fait pas référence au nouvel objet.

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


68
2017-08-12 02:16



exports et module.exports sont les mêmes sauf si vous réaffectez exports dans votre module.

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

var exports = module.exports = {};

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

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

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

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

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

Remarquerez que module.exports est l'argument le plus à gauche.

Attacher des propriétés à exports n'est pas la même chose puisque vous ne le réattribuez pas. C'est pourquoi ça marche

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

41
2017-09-25 15:10



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

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

exports et module.exports les deux pointent vers le même objet. exports est une variable et module.exports est un attribut de l'objet module.

Dites que j'écris quelque chose comme ceci:

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

exports et module.exports maintenant pointer vers différents objets. La modification des exportations ne modifie plus module.exports.

Lorsque la fonction d'importation inspecte module.exports il obtient {b:12}


21
2018-02-18 17:14



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

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

alors:

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)

10
2017-08-22 12:19



Voici une bonne description écrite sur les modules de nœuds dans node.js en action livre de Manning publication.
Ce qui est finalement exporté dans votre application est module.exports.
 exportations
est réglé simplement comme une référence mondiale à module.exports , qui est initialement défini comme objet vide auquel vous pouvez ajouter des propriétés. Alors exports.myFunc est juste une abréviation pour module.exports.myFunc.

En conséquence, si exportations est réglé sur autre chose, il brise la référence entre module.exports et exportations . Car module.exports est ce qui obtient vraiment exporté, exportations ne fonctionnera plus comme prévu - il ne fait pas référence module .exportations plus. Si vous voulez maintenir ce lien, vous pouvez faire module.exports référence exportations  encore comme suit:

module.exports = exports = db;

9
2017-07-14 12:47