javascript how - Quel est le but de Node.js module.exports et comment l'utilisez-vous?




to nodejs (9)

Quel est le but de Node.js module.exports et comment l'utilisez-vous?

Je ne peux pas trouver d'informations à ce sujet, mais il semble être une partie assez importante de Node.js comme je le vois souvent dans le code source.

Selon la documentation de Node.js :

module

Une référence au module actuel. En particulier, module.exports est identique à l'objet exports. Voir src/node.js pour plus d'informations.

Mais cela n'aide pas vraiment.

Que fait exactement module.exports , et que serait un exemple simple?


Answers

module.exports est l'objet qui est réellement retourné à la suite d'un appel require .

La variable exports est initialement définie sur le même objet (c'est-à-dire qu'il s'agit d'un raccourci "alias"), donc dans le code du module, vous écrirez généralement quelque chose comme ceci:

var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;

exporter (ou "exposer") les fonctions à portée interne myFunc1 et myFunc2 .

Et dans le code d'appel vous utiliseriez:

var m = require('mymodule');
m.myFunc1();

où la dernière ligne montre comment le résultat de require est (habituellement) juste un objet simple dont les propriétés peuvent être accédées.

NB: si vous écrasez les exports il ne se référera plus à module.exports . Donc, si vous souhaitez affecter un nouvel objet (ou une référence de fonction) aux exports vous devez également affecter ce nouvel objet à module.exports

Il est à noter que le nom ajouté à l'objet exports ne doit pas nécessairement être le même que le nom de portée interne du module pour la valeur que vous ajoutez, ce qui vous permet d'avoir:

var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required

suivi par:

var m = require('mymodule');
m.shortName(); // invokes module.myVeryLongInternalName

Notez que le mécanisme du module NodeJS est basé sur des modules CommonJS qui sont supportés dans de nombreuses autres implémentations comme RequireJS , mais aussi SproutCore , CouchDB , Wakanda , OrientDB , ArangoDB , RingoJS , TeaJS , SilkJS , curl.js , ou encore Adobe Photoshop (via PSLib ). Vous pouvez trouver la liste complète des implémentations connues here .

À moins que votre module n'utilise des fonctionnalités ou des modules spécifiques aux nœuds, je vous encourage fortement à utiliser les exports au lieu de module.exports qui ne fait pas partie du standard CommonJS , et qui n'est généralement pas supporté par d'autres implémentations.

Une autre caractéristique spécifique de NodeJS est lorsque vous affectez une référence à un nouvel objet à exports au lieu de simplement ajouter des propriétés et des méthodes, comme dans le dernier exemple fourni par Jed Watson dans ce thread. Je déconseillerais personnellement cette pratique car cela rompt le support de référence circulaire du mécanisme des modules CommonJS. Il n'est alors pas supporté par toutes les implémentations et l'exemple de Jed devrait alors être écrit de cette façon (ou similaire) pour fournir un module plus universel:

(sayhello.js):

exports.run = function() {
    console.log("Hello World!");
}

(app.js):

var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"

Ou en utilisant les fonctionnalités ES6

(sayhello.js):

Object.assign(exports, {
    // Put all your public API here
    sayhello() {
        console.log("Hello World!");
    }
});

(app.js):

const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"

PS: Il semble qu'Appcelerator implémente aussi des modules CommonJS, mais sans le support de référence circulaire (voir: Modules Appcelerator et CommonJS (mise en cache et références circulaires) )


Un module encapsule le code associé dans une seule unité de code. Lors de la création d'un module, cela peut être interprété comme le déplacement de toutes les fonctions associées dans un fichier.

Supposons qu'il existe un fichier Hello.js qui inclut deux fonctions

sayHelloInEnglish = function() {
  return "Hello";
};
sayHelloInSpanish = function() {
  return "Hola";
};

Nous n'écrivons une fonction que lorsque l'utilité du code est plus d'un appel.

Supposons que nous voulons augmenter l'utilité de la fonction dans un fichier différent, par exemple World.js, dans ce cas l'exportation d'un fichier entre en image qui peut être obtenue par module.exports.

Vous pouvez simplement exporter la fonction par le code ci-dessous

var anyVariable={
 sayHelloInEnglish = function() {
      return "Hello";
    };
  sayHelloInSpanish = function() {
      return "Hola";
    }; 
}
module.export=anyVariable;

Maintenant vous avez juste besoin d'exiger le nom du fichier dans World.js pour pouvoir utiliser ces fonctions

var world= require("./hello.js");

le lien de référence est comme ceci:

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

les propriétés des exports ou module.exports , telles que les fonctions ou les variables, seront exposées à l'extérieur

il y a quelque chose que vous devez accorder plus d'attention: ne pas override exportations.

Pourquoi ?

car exporte uniquement la référence de module.exports, vous pouvez ajouter les propriétés aux exportations, mais si vous remplacez les exportations, le lien de référence sera rompu.

bon exemple :

exports.name = 'william';

exports.getName = function(){
   console.log(this.name);
}

mauvais exemple:

exports = 'william';

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

Si vous voulez juste exposer une seule fonction ou variable, comme ceci:

// test.js
var name = 'william';

module.exports = function(){
    console.log(name);
}   

// index.js
var test = require('./test');
test();

ce module n'a exposé qu'une seule fonction et la propriété de nom est privée pour l'extérieur.


la propriété module.exports ou l'objet exports permet à un module de sélectionner ce qui doit être partagé avec l'application

J'ai une vidéo sur module_export disponible here


Lorsque vous module.exports votre code de programme sur plusieurs fichiers, module.exports est utilisé pour publier des variables et des fonctions pour le consommateur d'un module. L'appel require() dans votre fichier source est remplacé par module.exports correspondant chargé depuis le module.

N'oubliez pas lors de l'écriture de modules

  • Les modules de chargement sont mis en cache, seul l'appel initial évalue JavaScript.
  • Il est possible d'utiliser des variables et des fonctions locales dans un module, tout ne doit pas être exporté.
  • L'objet module.exports est également disponible en tant module.exports abrégée. Mais lorsque vous renvoyez une seule fonction, utilisez toujours module.exports .

Selon: "Modules Partie 2 - Modules d'écriture" .


Cela a déjà été répondu, mais je voulais ajouter quelques précisions ...

Vous pouvez utiliser exports et module.exports pour importer du code dans votre application comme ceci:

var mycode = require('./path/to/mycode');

Le cas d'utilisation basique que vous verrez (par exemple dans l'exemple de code ExpressJS) est que vous définissez les propriétés de l'objet exports dans un fichier .js que vous importez ensuite en utilisant require()

Ainsi, dans un exemple de comptage simple, vous pourriez avoir:

(counter.js):

var count = 1;

exports.increment = function() {
    count++;
};

exports.getCount = function() {
    return count;
};

... puis dans votre application (web.js, ou tout autre fichier .js):

var counting = require('./counter.js');

console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2

En termes simples, vous pouvez considérer les fichiers requis comme des fonctions qui renvoient un seul objet, et vous pouvez ajouter des propriétés (chaînes, nombres, tableaux, fonctions, n'importe quoi) à l'objet renvoyé en les définissant à l' exports .

Parfois, vous voulez que l'objet renvoyé à partir d'un appel require() soit une fonction que vous pouvez appeler, plutôt qu'un simple objet avec des propriétés. Dans ce cas, vous devez également définir module.exports , comme ceci:

(sayhello.js):

module.exports = exports = function() {
    console.log("Hello World!");
};

(app.js):

var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"

La différence entre exports et module.exports est mieux expliquée dans cette réponse ici .


Vous devez prendre quelques précautions si vous attribuez une référence à un nouvel objet à exports et / ou à modules.exports :

1. Toutes les propriétés / méthodes précédemment attachées aux exports originaux ou au module.exports sont bien sûr perdues car l'objet exporté va maintenant en référencer un autre nouveau

Celui-ci est évident, mais si vous ajoutez une méthode exportée au début d'un module existant, assurez-vous que l'objet exporté natif ne fait pas référence à un autre objet à la fin

exports.method1 = function () {}; // exposed to the original exported object
exports.method2 = function () {}; // exposed to the original exported object

module.exports.method3 = function () {}; // exposed with method1 & method2

var otherAPI = {
    // some properties and/or methods
}

exports = otherAPI; // replace the original API (works also with module.exports)

2. Dans le cas où l'un des exports ou module.exports référence une nouvelle valeur, ils ne font plus référence au même objet

exports = function AConstructor() {}; // override the original exported object
exports.method2 = function () {}; // exposed to the new exported object

// method added to the original exports object which not exposed any more
module.exports.method3 = function () {}; 

3. Conséquence trompeuse. Si vous modifiez la référence aux exports et module.exports , difficile de dire quelle API est exposée (il semble que module.exports gagne)

// override the original exported object
module.exports = function AConstructor() {};

// try to override the original exported object
// but module.exports will be exposed instead
exports = function AnotherConstructor() {}; 

Aujourd'hui - 2018.06.27, je propose une comparaison temporelle de solutions JS pures. Cela peut être utile pour les personnes qui souhaitent obtenir / mesurer du temps dans JS de manière légère / efficace (par exemple, pour des applications en temps réel telles que des simulations, des jeux, etc.).

Testé sur MacOs High Sierra 10.13.3 sur Chrome 67.0.3396.99 (64 bits), Safari 11.0.3 (13604.5.6), Firefox 59.0.2 (64 bits). Sur la capture d'écran ci-dessous, je vous montre les résultats pour le navigateur le plus rapide (Safari):

Comme je le constate, Date.now() est la méthode la plus rapide pour obtenir l’horodatage des trois navigateurs. Safari a 19,2 millions d'opérations par seconde, Firefox 16,1 millions, Chrome 7,8 millions.

La new Date()*1 était la plus lente pour Chrome (2,8M) et Firefox (2,6M). Le Number(new Date()) était le plus lent pour Safari (2,9M).

Le code JS gagnant est donc Date.now() et le navigateur le plus rapide est Safari (2x plus rapide que le chrome!).

Vous pouvez effectuer des tests sur votre machine ici: https://jsperf.com/timestamp-test-x .







javascript node.js