module.exports vs Exporte in Node.js


725

Ich habe den folgenden Vertrag in einem Node.js-Modul gefunden:

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

Ich frage mich, was der Unterschied zwischen module.exportsund ist exportsund warum beide hier verwendet werden.




6
Der Link "Für die Nachwelt" wurde aktualisiert: nodejs.org/docs/latest/api/modules.html#modules_module_exports
Zeke

8
Es geht nur um Referenzen. Stellen Sie sich Exporte wie ein lokales variables Objekt vor, das auf module.exports zeigt. Wenn Sie den Wert von Exporten überschreiben, verlieren Sie den Verweis auf module.exports, und module.exports wird als öffentliche Schnittstelle verfügbar gemacht.
Gabriel Llamas

14
Kurzzusammenfassung: Beide exportsund module.exportszeigen auf dasselbe Objekt, es sei denn, Sie weisen eines neu zu. Und am Ende module.exportswird zurückgegeben. Wenn Sie also exportseiner Funktion neu zugewiesen wurden , erwarten Sie keine Funktion, da diese nicht zurückgegeben wird. Wenn Sie jedoch eine exports.func = function...solche Funktion zugewiesen hätten, hätte das resultierende Objekt die Eigenschaft func mit der Funktion als Wert. Weil Sie die Eigenschaft zu dem Objekt hinzugefügt haben, auf das exports
Muhammad Umer

Antworten:


426

Durch die Einstellung module.exportskann die database_moduleFunktion wie eine Funktion aufgerufen werden, wenn required. Durch einfaches Festlegen kann exportsdie Funktion nicht exportiert werden, da der Knoten die Objektreferenzen exportiert module.exports. Mit dem folgenden Code kann der Benutzer die Funktion nicht aufrufen.

module.js

Folgendes wird nicht funktionieren.

exports = nano = function database_module(cfg) {return;}

Folgendes funktioniert, wenn module.exportseingestellt ist.

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

Konsole

var func = require('./module.js');
// the following line will **work** with module.exports
func();

Grundsätzlich exportiert node.js nicht das Objekt, auf das exportsaktuell verwiesen wird, sondern die Eigenschaften der exportsursprünglich referenzierten Objekte . Obwohl Node.js die Objektreferenzen exportiert module.exports, können Sie sie wie eine Funktion aufrufen.


2. am wenigsten wichtiger Grund

Sie setzen beide module.exportsund stellen exportssicher, dass exportsnicht auf das zuvor exportierte Objekt verwiesen wird. Indem Sie beide festlegen, verwenden Sie sie exportsals Abkürzung und vermeiden mögliche Fehler später.

Verwenden exports.prop = true statt module.exports.prop = trueSpeichern von Zeichen und vermeidet Verwirrung.


8
@ajostergaard: Es ist zufällig der Name der Bibliothek, aus der das Beispiel des OP stammt. In dem Modul ermöglicht es dem Autor, Dinge wie nano.version = '3.3'statt zu schreiben module.exports.version = '3.3', was etwas klarer liest. (Beachten Sie, dass dies nanoeine lokale Variable ist, die kurz vor dem
Festlegen der Modulexporte

3
@lime - danke - ich bin froh, dass es weitgehend irrelevant ist, denn wenn es nicht so wäre, würde ich alles völlig missverstanden haben. : - | :)
ostergaard

Hey Lime, das ist eine ziemlich alte Antwort, aber ich hoffe, du kannst etwas klarstellen. Wenn ich einstellen würde, module.exportsaber nicht exports , würde mein Code trotzdem funktionieren? Vielen Dank für jede Hilfe!
Asad Saeeduddin

1
@Asad Ja, die Funktion wird ordnungsgemäß exportiert, vorausgesetzt, Sie haben festgelegtmodule.exports
Lime

@ Liam danke für die wertvolle Antwort. Einige weitere Abfragen - Welche Werte werden beim Eintrag von server.js für module.exports und export erwartet? Wird erwartet, dass module.exports null ist und Exporte auf ein leeres Objekt gesetzt werden? Ist dies ein Vermächtnis oder gibt es einen gültigen Anwendungsfall, um Exporte und module.exports jemals auf zwei verschiedene Objekte zu verweisen?
Sushil

504

Obwohl die Frage vor langer Zeit beantwortet und akzeptiert wurde, möchte ich nur meine 2 Cent teilen:

Sie können sich vorstellen, dass am Anfang Ihrer Datei so etwas steht (nur zur Erklärung):

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

Geben Sie hier die Bildbeschreibung ein

Was auch immer Sie tun, denken Sie daran, dass module.exportsNICHT exportsvon Ihrem Modul zurückgegeben wird, wenn Sie dieses Modul von einem anderen Ort benötigen.

Wenn Sie also etwas tun wie:

exports.a = function() {
    console.log("a");
}
exports.b = function() {
    console.log("b");
}

Sie fügen 2 Funktion aund bauf das Objekt , auf dem module.exportsPunkt zu, so dass das typeofdas zurückkehrende Ergebnis ein sein wird object:{ a: [Function], b: [Function] }

Dies ist natürlich das gleiche Ergebnis, das Sie erhalten, wenn Sie module.exportsin diesem Beispiel anstelle von verwenden exports.

Dies ist der Fall, wenn Sie möchten, dass Sie module.exportssich wie ein Container mit exportierten Werten verhalten. Wenn Sie dagegen nur eine Konstruktorfunktion exportieren möchten, sollten Sie etwas über die Verwendung von module.exportsoder wissen exports. (Denken module.exportsSie daran, dass dies zurückgegeben wird, wenn Sie etwas benötigen, nicht export).

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

Jetzt ist das typeofzurückgegebene Ergebnis 'function'und Sie können es anfordern und sofort wie folgt aufrufen:
var x = require('./file1.js')();weil Sie das zurückgegebene Ergebnis überschreiben, um eine Funktion zu sein.

Allerdings verwenden exportsSie nicht so etwas wie verwenden können:

exports = function Something() {
    console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function

Denn mit exportszeigt die Referenz nicht mehr auf das Objekt, auf das module.exportsPunkte zeigen, sodass keine Beziehung mehr zwischen exportsund besteht module.exports. In diesem Fall zeigt module.exportsimmer noch auf das leere Objekt, {}das zurückgegeben wird.

Akzeptierte Antworten von einem anderen Thema sollten ebenfalls helfen: Geht Javascript als Referenz?


2
Schöne Erklärung, aber ich verstehe immer noch nicht, wie Sie module.exportsein Modul vollständig weglassen können , zum Beispiel in diesem npmPaket: github.com/tj/consolidate.js/blob/master/lib/consolidate.js
CodyBugstein

4
@Imray die Erklärung ist hier: Geht JavaScript als Referenz? exports.a = function(){}; works, exports = function(){} doesn't work
Cirpo

29
oooo endlich erklärt diese Antwort es. Grundsätzlich bezieht sich Export auf ein Objekt, dem Sie Eigenschaften hinzufügen können. Wenn Sie es jedoch der Funktion neu zuweisen , können Sie dem ursprünglichen Objekt keine Eigenschaft mehr zuordnen. Exportieren Sie jetzt den Verweis auf die Funktion, während module.exports noch auf dieses Objekt zeigt und da es zurückgegeben wird. Man kann sagen, dass der Export im Grunde genommen Müll war.
Muhammad Umer

5
Also, was ist der Sinn der Verwendung exports? Warum nicht einfach immer verwenden, module.exportswenn es sich nur um eine variable Neuzuweisung handelt? Scheint mir verwirrend.
jedd.ahyoung

1
@ jedd.ahyoung Es ist weniger umständlich zu schreiben exports.somethingstattmodule.exports.something
Srle

209

Grundsätzlich liegt die Antwort darin, was wirklich passiert, wenn ein Modul per requireAnweisung benötigt wird . Angenommen, dies ist das erste Mal, dass das Modul benötigt wird.

Zum Beispiel:

var x = require('file1.js');

Inhalt von file1.js:

module.exports = '123';

Wenn die obige Anweisung ausgeführt wird, wird ein ModuleObjekt erstellt. Seine Konstruktorfunktion ist:

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 = [];
}

Wie Sie sehen, hat jedes Modulobjekt eine Eigenschaft mit Namen exports. Dies ist, was schließlich als Teil von zurückgegeben wird require.

Der nächste Schritt von require besteht darin, den Inhalt von file1.js in eine anonyme Funktion wie folgt zu verpacken:

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
});

Diese anonyme Funktion wird folgendermaßen aufgerufen. moduleHier wird auf das Modulezuvor erstellte Objekt verwiesen.

(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");

Wie wir in der Funktion sehen können, exportsbezieht sich das formale Argument auf module.exports. Im Wesentlichen ist dies eine Annehmlichkeit für den Modulprogrammierer.

Diese Bequemlichkeit muss jedoch mit Sorgfalt ausgeübt werden. Wenn Sie versuchen, Exporten ein neues Objekt zuzuweisen, stellen Sie dies auf jeden Fall auf diese Weise sicher.

exports = module.exports = {};

Wenn wir es falsch machen , module.exportszeigen wir immer noch auf das Objekt, das als Teil der Modulinstanz erstellt wurde.

exports = {};

Infolgedessen hat das Hinzufügen von etwas zum obigen Exportobjekt keine Auswirkung auf das module.exports-Objekt und nichts wird als Teil von require exportiert oder zurückgegeben.


8
Verloren mich hierexports = module.exports = {};
Riesen Elk

2
Ich denke, dies sollte die beste Antwort sein, es erklärt, warum func()@ Williams Antwort fehlschlägt!
Turteltaube

2
Ich sehe keinen Vorteil in exports = module.exports = app;der letzten Zeile des Codes hinzuzufügen . Es scheint, als würde das module.exportsexportiert und wir werden es nie verwenden exports, da es sich wieder in der letzten Zeile des Codes befindet. Also, warum fügen wir nicht einfach hinzumodule.exports = app;
lvarayut

79

Anfangs, module.exports=exportsund die requireFunktion gibt zurück, auf die sich das Objekt module.exportsbezieht.

Wenn wir dem Objekt beispielsweise eine Eigenschaft hinzufügen , beziehen sich exports.a=1module.exports und export immer noch auf dasselbe Objekt. Wenn wir also require aufrufen und das Modul einer Variablen zuweisen, hat die Variable eine Eigenschaft a und ihr Wert ist 1;

Aber wenn wir außer Kraft setzen einer von ihnen, zum Beispiel exports=function(){}, dann sind sie anders jetzt: Exporte bezieht sich auf ein neues Objekt und module.exports beziehen sich auf das ursprüngliche Objekt. Und wenn wir die Datei benötigen, wird das neue Objekt nicht zurückgegeben, da module.exports nicht auf das neue Objekt verweist.

Für mich werde ich weiterhin neue Eigenschaften hinzufügen oder beide einem neuen Objekt überschreiben. Nur überschreiben ist nicht richtig. Und denken Sie daran, das module.exportsist der wahre Chef.


1
Ja, das ist eigentlich die wahre Antwort. Es ist prägnant und klar. Andere mögen Recht haben, aber voller ausgefallener Begriffe und konzentrieren sich nicht genau auf die Antwort auf diese Frage.
Khoa

Dies ist bei weitem die klarste Antwort! Falls Sie es als Lesezeichen speichern
Lambdarookie

56

exportsund module.exportssind gleich, es sei denn, Sie weisen exportsinnerhalb Ihres Moduls eine Neuzuweisung zu .

Der einfachste Weg, darüber nachzudenken, besteht darin, zu denken, dass diese Zeile implizit oben in jedem Modul steht.

var exports = module.exports = {};

Wenn Sie innerhalb Ihres Moduls eine Neuzuweisung vornehmen exports, weisen Sie es innerhalb Ihres Moduls neu zu und es ist nicht mehr gleich module.exports. Wenn Sie eine Funktion exportieren möchten, müssen Sie daher Folgendes tun:

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

Wenn Sie einfach Ihre zugewiesen function() { ... }zu exports, würden Sie werden Neuzuweisung exportszu keinem längeren Punkt module.exports.

Wenn Sie nicht module.exportsjedes Mal auf Ihre Funktion verweisen möchten , können Sie Folgendes tun:

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

Beachten Sie, dass dies module.exportsdas Argument ganz links ist.

Das Anhängen von Eigenschaften an exportsist nicht dasselbe, da Sie es nicht neu zuweisen. Deshalb funktioniert das

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

9
Dies war von allen Antworten am einfachsten zu verstehen!
Adarsh ​​Konchady

2
Schön und unkompliziert
Fibono

1
Einfache und einfachere Möglichkeit, diese Funktion zu verstehen.
FilipeCanatto

27

JavaScript übergibt Objekte per Kopie einer Referenz

Es ist ein subtiler Unterschied, wie Objekte in JavaScript als Referenz übergeben werden.

exportsund module.exportsbeide zeigen auf dasselbe Objekt. exportsist eine Variable und module.exportsein Attribut des Modulobjekts.

Angenommen, ich schreibe so etwas:

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

exportsund module.exportsjetzt auf verschiedene Objekte zeigen. Durch Ändern von Exporten wird module.exports nicht mehr geändert.

Wenn die Importfunktion prüft, wird module.exportses{b:12}


6
Beste Antwort imho!
Herr AJ

1
"JavaScript geht als Referenz" - Nr.
xehpuk

13

Ich mache nur einen Test, es stellt sich heraus, dass es im Modulcode von nodejs ungefähr so ​​aussehen sollte:

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

damit:

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: aber in diesem Fall

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)

Lyman ist also module.exportseine Art "Real-Deal", von dem der Knoten ausgeht, aber irgendwann müssen Sie alles hinzufügen exports, es module.exportssei denn, Sie verwenden ein exports.namespace(Fall 2 oben), was in diesem Fall so zu sein scheint Knoten hat ein ' extends(module.exports, exports);Hinzufügen aller' Namespaces ' exportszum module.exportsObjekt ausgeführt? Mit anderen Worten, wenn Sie verwenden exports, möchten Sie wahrscheinlich Eigenschaften festlegen?
Cody

11

Hier ist eine gute Beschreibung der Knotenmodule in node.js im Aktionsbuch der Manning- Veröffentlichung.
Was letztendlich in Ihre Anwendung exportiert wird, ist module.exports.
Der Export
wird einfach als globaler Verweis auf module.exports eingerichtet , das zunächst als leeres Objekt definiert ist, dem Sie Eigenschaften hinzufügen können. So exports.myFunc ist nur eine Abkürzung für module.exports.myFunc .

Als Ergebnis , wenn die Ausfuhren auf etwas anderes gesetzt, bricht es die Referenz zwischen module.exports und Exporte . Weil module.exportswird wirklich exportiert, Exporte funktionieren nicht mehr wie erwartet - es verweist nicht mehr auf das Modul .exports . Wenn Sie auf diesen Link erhalten wollen, können Sie machen module.exports Referenz Exporte wieder wie folgt:

module.exports = exports = db;

8

Ich habe einige Tests durchlaufen und ich denke, dies könnte etwas Licht in das Thema bringen ...

app.js::

var ...
  , routes = require('./routes')
  ...;
...
console.log('@routes', routes);
...

Versionen von /routes/index.js:

exports = function fn(){}; // outputs "@routes {}"

exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

module.exports = function fn(){};  // outputs "@routes function fn(){}"

module.exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

Ich habe sogar neue Dateien hinzugefügt:

./routes/index.js::

module.exports = require('./not-index.js');
module.exports = require('./user.js');

./routes/not-index.js::

exports = function fn(){};

./routes/user.js::

exports = function user(){};

Wir erhalten die Ausgabe "@routes {}"


./routes/index.js::

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js::

exports = function fn(){};

./routes/user.js::

exports = function user(){};

Wir erhalten die Ausgabe "@routes {fn: {}, user: {}}"


./routes/index.js::

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js::

exports.fn = function fn(){};

./routes/user.js::

exports.user = function user(){};

Wir bekommen die Ausgabe "@routes {user: [Funktion: user]}" Wenn wir ändern user.jszu { ThisLoadedLast: [Function: ThisLoadedLast] }, wir die Ausgabe erhalten "@routes {ThisLoadedLast: [Funktion: ThisLoadedLast]}".


Aber wenn wir modifizieren ./routes/index.js...

./routes/index.js::

module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');

./routes/not-index.js::

exports.fn = function fn(){};

./routes/user.js::

exports.ThisLoadedLast = function ThisLoadedLast(){};

... wir erhalten "@routes {fn: {fn: [Funktion: fn]}, ThisLoadedLast: {ThisLoadedLast: [Funktion: ThisLoadedLast]}}"

Daher würde ich vorschlagen, immer module.exportsin Ihren Moduldefinitionen zu verwenden.

Ich verstehe nicht ganz, was intern mit Node los ist, aber bitte kommentieren Sie, ob Sie dies besser verstehen können, da ich sicher bin, dass es hilft.

- Viel Spaß beim Codieren


Ich denke, sie sind unnötig kompliziert und verwirrend. Es sollte transparent und intuitiv sein.
Ngungo

Genau. Es kann unter bestimmten Umständen für den Namespace nützlich sein, wird aber im Allgemeinen nichts machen oder brechen.
Cody

4

Dies zeigt, wie es require()in seiner einfachsten Form funktioniert, ein Auszug aus Eloquent JavaScript

Problem Es ist einem Modul nicht möglich, einen anderen Wert als das Exportobjekt, z. B. eine Funktion, direkt zu exportieren. Beispielsweise möchte ein Modul möglicherweise nur den Konstruktor des von ihm definierten Objekttyps exportieren. Dies ist derzeit nicht möglich, da require immer das von exportsihm erstellte Objekt als exportierten Wert verwendet.

Lösung Stellen Sie Modulen eine andere Variable zur Verfügung, modulebei der es sich um ein Objekt mit einer Eigenschaft handelt exports. Diese Eigenschaft zeigt zunächst auf das leere Objekt, das von require erstellt wurde, kann jedoch mit einem anderen Wert überschrieben werden, um etwas anderes zu exportieren.

function require(name) {
  if (name in require.cache)
    return require.cache[name];
  var code = new Function("exports, module", readFile(name));
  var exports = {}, module = {exports: exports};
  code(exports, module);
  require.cache[name] = module.exports;
  return module.exports;
}
require.cache = Object.create(null);

Ich musste dies in Node neu erstellen und ein paar Dinge testen, bis ich bekam, ich sauge. Grundsätzlich gibt die für das Modul erstellte innere Funktion niemals das Exportobjekt zurück. Das Objekt "Exporte" wird also im Modul nicht neu zugewiesen, z. B. wenn Sie versuchen, Exporte zu schreiben = "Dies ist jetzt eine Zeichenfolge" direkt. Das Objekt existiert nur als Referenz. Dies ist ein Verhalten, von dem ich glaube, dass ich es bis jetzt nicht richtig verstanden habe.
Danielgormly

4

Hier ist das Ergebnis von

console.log("module:");
console.log(module);

console.log("exports:");
console.log(exports);

console.log("module.exports:");
console.log(module.exports);

Geben Sie hier die Bildbeschreibung ein

Ebenfalls:

if(module.exports === exports){
    console.log("YES");
}else{
    console.log("NO");
}

//YES

Hinweis: Die CommonJS-Spezifikation erlaubt nur die Verwendung der Exportvariablen, um öffentliche Mitglieder verfügbar zu machen. Daher ist das genannte Exportmuster das einzige, das wirklich mit der CommonJS-Spezifikation kompatibel ist. Die Verwendung von module.exports ist eine Erweiterung von Node.js, um eine breitere Palette von Moduldefinitionsmustern zu unterstützen.


4
var a = {},md={};

// Erstens zeigen die Exporte und module.exports auf dasselbe leere Objekt

exp = a;//exports =a;
md.exp = a;//module.exports = a;

exp.attr = "change";

console.log(md.exp);//{attr:"change"}

// Wenn Sie exp auf ein anderes Objekt zeigen, anstatt es auf ein anderes Objekt zu zeigen. Die md.exp ist leer Objekt {}

var a ={},md={};
exp =a;
md.exp =a;

exp = function(){ console.log('Do nothing...'); };

console.log(md.exp); //{}

4

Aus den Dokumenten

Die Exportvariable ist im Bereich auf Dateiebene eines Moduls verfügbar und erhält den Wert von module.exports, bevor das Modul ausgewertet wird.

Es ermöglicht eine Verknüpfung, sodass module.exports.f = ... prägnanter als exports.f = .... geschrieben werden kann. Beachten Sie jedoch, dass wie bei jeder Variablen ein neuer Wert für den Export verwendet wird nicht mehr an module.exports gebunden:

Es ist nur eine Variable, die auf module.exports zeigt.


4

Ich fand diesen Link nützlich, um die obige Frage zu beantworten.

http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/

Hinzufügen zu den anderen Posts Das Modulsystem im Knoten tut dies

var exports = module.exports 

bevor Sie Ihren Code ausführen. Wenn Sie also exportieren = foo möchten, möchten Sie wahrscheinlich module.exports = exportieren = foo ausführen, aber die Verwendung von exports.foo = foo sollte in Ordnung sein


Git Link ist kaputt
Jesse Hattabaugh

Link ist jetzt behoben.
Paweł Gościcki

3

"Wenn Sie möchten, dass das Stammverzeichnis des Exports Ihres Moduls eine Funktion ist (z. B. ein Konstruktor), oder wenn Sie ein vollständiges Objekt in einer Zuweisung exportieren möchten, anstatt es einzeln zu erstellen, weisen Sie es stattdessen module.exports zu Exporte. " - http://nodejs.org/api/modules.html


3

module.exportsund exportsbeide zeigen auf dasselbe Objekt, bevor das Modul ausgewertet wird.

Jede Eigenschaft, die Sie dem module.exports Objekt hinzufügen, ist verfügbar, wenn Ihr Modul mithilfe der requireAnweisung in einem anderen Modul verwendet wird . exportsist eine Verknüpfung, die für dasselbe bereitgestellt wird. Zum Beispiel:

module.exports.add = (a, b) => a+b

ist gleichbedeutend mit Schreiben:

exports.add = (a, b) => a+b

Es ist also in Ordnung, solange Sie der exportsVariablen keinen neuen Wert zuweisen . Wenn Sie so etwas tun:

exports = (a, b) => a+b 

Wenn Sie ihm einen neuen Wert zuweisen, exportsverweist er nicht mehr auf das exportierte Objekt und bleibt daher lokal für Ihr Modul.

Wenn Sie vorhaben, module.exportsdem ursprünglich zur Verfügung gestellten ursprünglichen Objekt einen neuen Wert zuzuweisen, anstatt neue Eigenschaften hinzuzufügen, sollten Sie die folgenden Schritte in Betracht ziehen:

module.exports = exports = (a, b) => a+b

Die Website von Node.j hat eine sehr gute Erklärung dafür.


2

1.exports -> als Singleton-Dienstprogramm verwenden
2. Modul-Exporte -> als logische Objekte wie Service, Modell usw. Verwenden


2

Lassen Sie uns ein Modul mit zwei Möglichkeiten erstellen:

Einweg

var aa = {
    a: () => {return 'a'},
    b: () => {return 'b'}
}

module.exports = aa;

Zweiter Weg

exports.a = () => {return 'a';}
exports.b = () => {return 'b';}

Und so wird require () das Modul integrieren.

Erster Weg:

function require(){
    module.exports = {};
    var exports = module.exports;

    var aa = {
        a: () => {return 'a'},
        b: () => {return 'b'}
    }
    module.exports = aa;

    return module.exports;
}

Zweiter Weg

function require(){
    module.exports = {};
    var exports = module.exports;

    exports.a = () => {return 'a';}
    exports.b = () => {return 'b';}

    return module.exports;
}

2

warum beide hier verwendet werden

Ich glaube , sie wollen einfach nur klar sein , dass module.exports, exportsund nanoauf die gleiche Funktion - so dass Sie eine der Variablen verwenden , um die Funktion in der Datei aufzurufen. nanobietet einen Kontext für die Funktionsweise der Funktion.

exportswird nicht exportiert (nur module.exportswird), warum also auch das überschreiben?

Der Kompromiss zwischen Ausführlichkeit begrenzt das Risiko zukünftiger Fehler, z. B. die Verwendung exportsanstelle module.exportsder Datei. Es wird auch klargestellt, dass module.exportsund exportstatsächlich auf den gleichen Wert verweisen.


module.exports vs. exports

Solange Sie nicht neu zuweisen module.exportsoder exports(und stattdessen dem Objekt, auf das sich beide beziehen, Werte hinzufügen), haben Sie keine Probleme und können sicher verwenden exports, um präziser zu sein.

Wenn Sie eines der beiden Objekte einem Objekt zuweisen, zeigen sie jetzt auf verschiedene Stellen, was verwirrend sein kann, es sei denn, Sie möchten absichtlich module.exportsetwas Bestimmtes sein (z. B. eine Funktion).

Das Festlegen exportseines Nicht-Objekts ist wenig sinnvoll, da Sie es module.exports = exportsam Ende festlegen müssen, um es in anderen Dateien verwenden zu können.

let module = { exports: {} };
let exports = module.exports;

exports.msg = 'hi';
console.log(module.exports === exports); // true

exports = 'yo';
console.log(module.exports === exports); // false

exports = module.exports;
console.log(module.exports === exports); // true

module.exports = 'hello';
console.log(module.exports === exports); // false

module.exports = exports;
console.log(module.exports === exports); // true

Warum module.exportseiner Funktion zuweisen ?

Prägnanter! Vergleichen Sie, wie viel kürzer das 2. Beispiel ist:

helloWorld1.js: module.exports.hello = () => console.log('hello world');

app1.js: let sayHello = require('./helloWorld1'); sayHello.hello; // hello world

helloWorld2.js: module.exports = () => console.log('hello world');

app2.js: let sayHello = require('./helloWorld2'); sayHello; // hello world


2

Geben Sie hier die Bildbeschreibung ein

Jede von Ihnen erstellte Datei ist ein Modul. Modul ist ein Objekt. Es hat eine Eigenschaft namens, exports : {}die standardmäßig ein leeres Objekt ist.

Sie können Funktionen / Middleware erstellen und zu diesen leeren Exporten Objekt wie fügen exports.findById() => { ... } dann requireüberall in Ihrer Anwendung und Nutzung ...

controller / user.js

exports.findById = () => {
    //  do something
}

erfordern in route.js zu verwenden:

const {findyId} = './controllers/user'

2

Um die Unterschiede zu verstehen, müssen Sie zunächst verstehen, was Node.js zur Laufzeit mit jedem Modul macht. Node.js erstellt für jedes Modul eine Wrapper-Funktion:

 (function(exports, require, module, __filename, __dirname) {

 })()

Beachten Sie, dass der erste Parameter exportsein leeres Objekt ist und der dritte Parameter moduleein Objekt mit vielen Eigenschaften ist und eine der Eigenschaften benannt ist exports. Das exportskommt und module.exportskommt. Das erstere ist ein variables Objekt, und das letztere ist eine Eigenschaft des moduleObjekts.

Innerhalb des Moduls macht Node.js dies am Anfang automatisch: module.exports = exportsund kehrt schließlich zurück module.exports.

Sie können also sehen, dass eine Neuzuweisung eines Werts exportskeine Auswirkung hat module.exports. (Einfach weil exportsauf ein anderes neues Objekt zeigt, aber module.exportsimmer noch das alte enthält exports)

let exports = {};
const module = {};
module.exports = exports;

exports = { a: 1 }
console.log(module.exports) // {}

Wenn Sie jedoch die Eigenschaften von aktualisieren exports, hat dies sicherlich Auswirkungen auf module.exports. Weil beide auf dasselbe Objekt zeigen.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports.b = 2;
console.log(module.exports) // { a: 1, b: 2 }

Beachten Sie auch, dass module.exportses für exportsUpdates bedeutungslos erscheint , wenn Sie einen anderen Wert neu zuweisen. Jede Aktualisierung exportswird ignoriert, da sie module.exportsauf ein anderes Objekt verweist.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports = {
  hello: () => console.log('hello')
}
console.log(module.exports) // { hello: () => console.log('hello')}

0

In der Datei js module.js wird die Datei module.load system ausgeführt. Jedes Mal, wenn der Knoten eine Datei ausführt, wird der Inhalt Ihrer js-Datei wie folgt umbrochen

'(function (exports, require, module, __filename, __dirname) {',+
     //your js file content
 '\n});'

Aufgrund dieser Umhüllung in Ihren js-Quellcode können Sie auf Exporte, Anforderungen, Module usw. zugreifen. Dieser Ansatz wird verwendet, da es keine andere Möglichkeit gibt, Funktionen, die in js-Dateien geschrieben wurden, in eine andere zu übertragen.

Dann führt der Knoten diese umschlossene Funktion mit c ++ aus. In diesem Moment werden exportierte Objekte, die an diese Funktion übergeben wurden, gefüllt.

Sie können in dieser Funktion Parameter Exporte und Modul sehen. Tatsächlich ist Exporte ein öffentliches Mitglied der Modulkonstruktorfunktion.

Schauen Sie sich den folgenden Code an

Kopieren Sie diesen Code in b.js.

console.log("module is "+Object.prototype.toString.call(module));
console.log("object.keys "+Object.keys(module));
console.log(module.exports);
console.log(exports === module.exports);
console.log("exports is "+Object.prototype.toString.call(exports));
console.log('----------------------------------------------');
var foo = require('a.js');
console.log("object.keys of foo: "+Object.keys(foo));
console.log('name is '+ foo);
foo();

Kopieren Sie diesen Code nach a.js.

exports.name = 'hello';
module.exports.name = 'hi';
module.exports.age = 23;
module.exports = function(){console.log('function to module exports')};
//exports = function(){console.log('function to export');}

Jetzt mit Knoten ausführen

Dies ist die Ausgabe

module is [object Object]
object.keys id,exports,parent,filename,loaded,children,paths
{}
true

Export ist [Objekt Objekt]

object.keys von foo: name is function () {console.log ('Funktion zum Modul-Export')} Funktion zum Modul-Export

Entfernen Sie nun die kommentierte Zeile in a.js und kommentieren Sie die Zeile über dieser Zeile. Entfernen Sie die letzte Zeile von b.js und führen Sie sie aus.

In der Javascript-Welt können Sie ein als Parameter übergebenes Objekt nicht neu zuweisen, aber Sie können das öffentliche Element der Funktion ändern, wenn das Objekt dieser Funktion als Parameter für eine andere Funktion festgelegt wurde

erinnere dich

Verwenden Sie module.exports nur dann, wenn Sie bei Verwendung des Schlüsselworts require eine Funktion erhalten möchten. im obigen Beispiel var foo = require (a.js); Sie können sehen, dass wir foo als Funktion aufrufen können.

So erklärt die Knotendokumentation: "Das Exportobjekt wird vom Modulsystem erstellt. Manchmal ist dies nicht akzeptabel. Viele möchten, dass ihr Modul eine Instanz einer Klasse ist. Weisen Sie dazu das gewünschte Exportobjekt module.exports zu."


0
  1. Beides module.exportsund exportszeigen auf dasselbe function database_module(cfg) {...}.

    1| var a, b;
    2| a = b = function() { console.log("Old"); };
    3|     b = function() { console.log("New"); };
    4|
    5| a(); // "Old"
    6| b(); // "New"

    Sie können bin Zeile 3 auf ändern a, die Ausgabe ist umgekehrt. Die Schlussfolgerung lautet:

    aund bsind unabhängig.

  2. Also module.exports = exports = nano = function database_module(cfg) {...}ist gleichbedeutend mit:

    var f = function database_module(cfg) {...};
    module.exports = f;
    exports = f;

    Angenommen, das Obige ist module.js, was von erforderlich ist foo.js. Die Vorteile von module.exports = exports = nano = function database_module(cfg) {...}sind jetzt klar:

    • In foo.js, da module.exportsist require('./module.js'):

      var output = require('./modules.js')();
    • In moduls.js: Sie können exportsanstelle von verwenden module.exports.

Also, werden Sie , wenn beide glücklich sein exportsund module.exportsauf die gleiche Sache zeigt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.