Sur cette page ( http://docs.nodejitsu.com/articles/getting-started/what-is-require ), il est indiqué que "Si vous souhaitez définir l'objet d'exportations comme une fonction ou un nouvel objet, vous devez utiliser l'objet module.exports. "
Ma question est pourquoi.
// right
module.exports = function () {
console.log("hello world")
}
// wrong
exports = function () {
console.log("hello world")
}
J'ai console.logged le résultat (result=require(example.js)
) et le premier est [Function]
le deuxième est {}
.
Pourriez-vous s'il vous plaît expliquer la raison derrière cela? J'ai lu le post ici: module.exports vs exports dans Node.js . C'est utile, mais n'explique pas pourquoi il est conçu de cette façon. Y aura-t-il un problème si la référence des exportations est renvoyée directement?
module
est un objet JavaScript simple avec une propriété exports
. exports
est une variable JavaScript simple dont la valeur est définie sur module.exports
. À la fin de votre fichier, node.js 'retournera' module.exports
à la fonction require
. Voici un moyen simplifié d’afficher un fichier JS dans Node:
var module = { exports: {} };
var exports = module.exports;
// your code
return module.exports;
Si vous définissez une propriété sur exports
, comme exports.a = 9;
, cela définira également module.exports.a
, car les objets sont transmis en tant que références en JavaScript, ce qui signifie que si vous définissez plusieurs variables de la même manière objet, ils sont tous le même objet; alors exports
et module.exports
sont le même objet.
Mais si vous définissez exports
sur quelque chose de nouveau, il ne sera plus réglé sur module.exports
, de sorte que exports
et module.exports
ne sont plus le même objet.
La réponse de Renée est bien expliquée. Ajout à la réponse avec un exemple:
Node fait beaucoup de choses dans votre fichier et l'un des plus importants est le WRAPPING de votre fichier. Le code source de nodejs "module.exports" est renvoyé. Permet de prendre du recul et de comprendre le wrapper. Supposons que vous ayez
saluer.js
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
le code ci-dessus est encapsulé sous la forme IIFE (Expression de fonction immédiatement appelée) dans le code source de nodejs, comme suit:
(function (exports, require, module, __filename, __dirname) { //add by node
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
}).apply(); //add by node
return module.exports; //add by node
et la fonction ci-dessus est appelée (.apply ()) et renvoyée module.exports. À ce stade, module.exports et exportations pointant vers la même référence.
Maintenant, imaginez que vous ré-écriviez greet.js en tant que
exports = function () {
console.log('Hello World');
};
console.log(exports);
console.log(module.exports);
la sortie sera
[Function]
{}
la raison en est: module.exports est un objet vide. Nous n'avons pas défini quoi que ce soit sur module.exports. Nous avons plutôt défini exports = function () ..... dans le nouveau message greet.js. Ainsi, module.exports est vide.
Techniquement, les exportations et module.exports doivent pointer vers la même référence (c'est correct !!). Mais nous utilisons "=" lors de l'affectation de function () .... aux exportations, ce qui crée un autre objet dans la mémoire. Ainsi, module.exports et exports produisent des résultats différents. En ce qui concerne les exportations, nous ne pouvons pas le remplacer.
Maintenant, imaginez que vous réécriviez (ceci s'appelle Mutation) greet.js (faisant référence à Renee) comme
exports.a = function() {
console.log("Hello");
}
console.log(exports);
console.log(module.exports);
la sortie sera
{ a: [Function] }
{ a: [Function] }
Comme vous pouvez le voir, module.exports et les exportations pointent vers la même référence qui est une fonction. Si vous définissez une propriété sur les exportations, elle le sera sur module.exports car, dans JS, les objets sont passés par référence.
La conclusion est toujours d'utiliser module.exports pour éviter toute confusion. J'espère que cela t'aides. Bonne codage :)
En outre, une chose qui peut aider à comprendre:
math.js
this.add = function (a, b) {
return a + b;
};
client.js
var math = require('./math');
console.log(math.add(2,2); // 4;
Super, dans ce cas:
console.log(this === module.exports); // true
console.log(this === exports); // true
console.log(module.exports === exports); // true
Ainsi, par défaut, "this" est égal à module.exports.
Toutefois, si vous modifiez votre implémentation pour:
math.js
var add = function (a, b) {
return a + b;
};
module.exports = {
add: add
};
Dans ce cas, cela fonctionnera bien, cependant, "ceci" n'est plus égal à module.exports, car un nouvel objet a été créé.
console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false
Et maintenant, ce qui sera retourné par l'exigence, c'est ce qui a été défini dans le module.exports, pas celui-ci ou les exportations, plus.
Une autre façon de le faire serait:
math.js
module.exports.add = function (a, b) {
return a + b;
};
Ou:
math.js
exports.add = function (a, b) {
return a + b;
};
La réponse de René sur la relation entre exports
et module.exports
est assez claire, il s'agit de références javascript. Je veux juste ajouter que:
Nous voyons cela dans de nombreux modules de nœuds:
var app = exports = module.exports = {};
Cela garantira que même si nous modifiions module.exports, nous pouvons toujours utiliser les exportations en faisant en sorte que ces deux variables pointent vers le même objet.