En regardant un aléatoire fichier source du cadre express
pour NodeJS
, il y a deux lignes de code que je ne comprends pas (ces lignes de code sont typiques de presque tous les fichiers NodeJS).
/**
* Expose `Router` constructor.
*/
exports = module.exports = Router;
et
/**
* Expose HTTP methods.
*/
var methods = exports.methods = require('./methods');
Je comprends que le premier morceau de code permet au reste des fonctions du fichier d'être exposées à l'application NodeJS , mais je ne comprends pas exactement comment cela fonctionne , ni ce que signifie le code de la ligne.
Que font
exports
etmodule.exports
signifie vraiment?
Je crois que le 2ème morceau de code permet aux fonctions du fichier d'accéder à methods
, mais encore une fois, comment fait-il exactement cela.
Fondamentalement, quels sont ces mots magiques: module
et exports
?
Pour être plus précis:
module
est la variable de portée globale à l'intérieur d'un fichier.
Donc, si vous appelez require("foo")
alors:
// foo.js
console.log(this === module); // true
Il agit de la même manière que window
agit dans le navigateur.
Il y a aussi un autre objet global appelé global
que vous pouvez écrire et lire dans n'importe quel fichier que vous voulez, mais qui implique la mutation de la portée globale et c'est [~ # ~] mal [~ # ~]
exports
est une variable qui vit sur module.exports
. C'est essentiellement ce que vous exportez lorsqu'un fichier est requis.
// foo.js
module.exports = 42;
// main.js
console.log(require("foo") === 42); // true
Il y a un problème mineur avec exports
seul. Le contexte d'étendue _global + et module
ne sont pas différents . (Dans le navigateur, le contexte de portée globale et window
sont les mêmes).
// foo.js
var exports = {}; // creates a new local variable called exports, and conflicts with
// living on module.exports
exports = {}; // does the same as above
module.exports = {}; // just works because its the "correct" exports
// bar.js
exports.foo = 42; // this does not create a new exports variable so it just works
Pour développer la réponse de Raynos ...
exports
est fondamentalement un alias pour module.exports
- Je recommande simplement de ne pas l'utiliser. Vous pouvez exposer les méthodes et les propriétés d'un module en les définissant sur module.exports
, comme suit:
//file 'module1.js'
module.exports.foo = function () { return 'bar' }
module.exports.baz = 5
Ensuite, vous y accédez dans votre code:
var module1 = require('module1')
console.log(module1.foo())
console.log(module1.baz)
Vous pouvez également remplacermodule.exports
Entièrement pour fournir simplement un seul objet sur demande:
//glorp.js
module.exports = function () {
this.foo = function () { return 'bar' }
this.baz = 5
return this // need to return `this` object here
}
Vous avez maintenant un joli prototype:
var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz)
Il existe une myriade d'autres façons de jouer avec module.exports
Et require
. N'oubliez pas, require('foo')
renvoie toujours la même instance même si vous l'appelez plusieurs fois.
Pour que les éléments suivants fonctionnent,
var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz)
this
doit être retourné dans la fonction affectée à module.exports
. Sinon, vous obtiendrez un TypeError
:
console.log(g1.foo())
^
TypeError: Cannot read property 'foo' of undefined
Vous pouvez trouver la meilleure réponse dans le code source de node.js. Si quelqu'un a besoin de votre module js, votre script se transforme en fonction par nœud comme suit (voir src/node.js).
// require function does this..
(function (exports, require, module, __filename, __dirname) {
... your javascript contents...
});
Le nœud enveloppera votre script. Ensuite, le script ci-dessus sera exécuté comme suit:
//module.js
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);
Donc dans votre script,
exports is just module.exports.
Dans votre script, vous pouvez ajouter quelque chose à cet objet exports (fonctions ..). La fonction require retournera cet objet. Il s'agit du système de modules de node.js (spécification commonJS).
Mais attention à ne pas modifier module.exports. Sinon, vos exportations actuelles n'auront aucun sens.
module est un objet qui représente ce que ce fichier source particulier aimerait exposer publiquement. Au lieu d'avoir quelque chose qui ressemble aux fichiers d'en-tête dans le monde c/c ++, vous décrivez ce que le module exportations en définissant cet objet. le runtime du nœud utilise ensuite cet objet pour déterminer ce qui est "public" dans votre module.
c'est un concept similaire à l'exportation de fonctions à partir d'une DLL dans le monde compilé. vous devez définir explicitement les fonctions accessibles au monde extérieur. cela aide à l'encapsulation et vous permet d'organiser vos bibliothèques de manière propre.
Le code du module est enveloppé dans module.exports (Le module, peut-être composé par un autre module). Il existe de nombreuses façons de créer un module, mais celui-ci est très courant (et mon préféré).
// Dependencies
// const module = require('module');
// Module object
var foo = {}
// Internal property
foo._a = 'a';
// "Public" property
foo.b = 'b';
// Method
foo.fu = function() { return 'fu' };
// Export
module.exports = foo;