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.exports
und ist exports
und warum beide hier verwendet werden.
javascript
node.js
commonjs
Andreas Köberle
quelle
quelle
exports
undmodule.exports
zeigen auf dasselbe Objekt, es sei denn, Sie weisen eines neu zu. Und am Endemodule.exports
wird zurückgegeben. Wenn Sie alsoexports
einer Funktion neu zugewiesen wurden , erwarten Sie keine Funktion, da diese nicht zurückgegeben wird. Wenn Sie jedoch eineexports.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 dasexports
Antworten:
Durch die Einstellung
module.exports
kann diedatabase_module
Funktion wie eine Funktion aufgerufen werden, wennrequired
. Durch einfaches Festlegen kannexports
die Funktion nicht exportiert werden, da der Knoten die Objektreferenzen exportiertmodule.exports
. Mit dem folgenden Code kann der Benutzer die Funktion nicht aufrufen.module.js
Folgendes wird nicht funktionieren.
Folgendes funktioniert, wenn
module.exports
eingestellt ist.Konsole
Grundsätzlich exportiert node.js nicht das Objekt, auf das
exports
aktuell verwiesen wird, sondern die Eigenschaften derexports
ursprünglich referenzierten Objekte . Obwohl Node.js die Objektreferenzen exportiertmodule.exports
, können Sie sie wie eine Funktion aufrufen.2. am wenigsten wichtiger Grund
Sie setzen beide
module.exports
und stellenexports
sicher, dassexports
nicht auf das zuvor exportierte Objekt verwiesen wird. Indem Sie beide festlegen, verwenden Sie sieexports
als Abkürzung und vermeiden mögliche Fehler später.Verwenden
exports.prop = true
stattmodule.exports.prop = true
Speichern von Zeichen und vermeidet Verwirrung.quelle
nano.version = '3.3'
statt zu schreibenmodule.exports.version = '3.3'
, was etwas klarer liest. (Beachten Sie, dass diesnano
eine lokale Variable ist, die kurz vor demmodule.exports
aber nichtexports
, würde mein Code trotzdem funktionieren? Vielen Dank für jede Hilfe!module.exports
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):
Was auch immer Sie tun, denken Sie daran, dass
module.exports
NICHTexports
von Ihrem Modul zurückgegeben wird, wenn Sie dieses Modul von einem anderen Ort benötigen.Wenn Sie also etwas tun wie:
Sie fügen 2 Funktion
a
undb
auf das Objekt , auf demmodule.exports
Punkt zu, so dass dastypeof
das zurückkehrende Ergebnis ein sein wirdobject
:{ a: [Function], b: [Function] }
Dies ist natürlich das gleiche Ergebnis, das Sie erhalten, wenn Sie
module.exports
in diesem Beispiel anstelle von verwendenexports
.Dies ist der Fall, wenn Sie möchten, dass Sie
module.exports
sich wie ein Container mit exportierten Werten verhalten. Wenn Sie dagegen nur eine Konstruktorfunktion exportieren möchten, sollten Sie etwas über die Verwendung vonmodule.exports
oder wissenexports
. (Denkenmodule.exports
Sie daran, dass dies zurückgegeben wird, wenn Sie etwas benötigen, nichtexport
).Jetzt ist das
typeof
zurü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
exports
Sie nicht so etwas wie verwenden können:Denn mit
exports
zeigt die Referenz nicht mehr auf das Objekt, auf dasmodule.exports
Punkte zeigen, sodass keine Beziehung mehr zwischenexports
und bestehtmodule.exports
. In diesem Fall zeigtmodule.exports
immer noch auf das leere Objekt,{}
das zurückgegeben wird.Akzeptierte Antworten von einem anderen Thema sollten ebenfalls helfen: Geht Javascript als Referenz?
quelle
module.exports
ein Modul vollständig weglassen können , zum Beispiel in diesemnpm
Paket: github.com/tj/consolidate.js/blob/master/lib/consolidate.jsexports.a = function(){}; works, exports = function(){} doesn't work
exports
? Warum nicht einfach immer verwenden,module.exports
wenn es sich nur um eine variable Neuzuweisung handelt? Scheint mir verwirrend.exports.something
stattmodule.exports.something
Grundsätzlich liegt die Antwort darin, was wirklich passiert, wenn ein Modul per
require
Anweisung benötigt wird . Angenommen, dies ist das erste Mal, dass das Modul benötigt wird.Zum Beispiel:
Inhalt von file1.js:
Wenn die obige Anweisung ausgeführt wird, wird ein
Module
Objekt erstellt. Seine Konstruktorfunktion ist:Wie Sie sehen, hat jedes Modulobjekt eine Eigenschaft mit Namen
exports
. Dies ist, was schließlich als Teil von zurückgegeben wirdrequire
.Der nächste Schritt von require besteht darin, den Inhalt von file1.js in eine anonyme Funktion wie folgt zu verpacken:
Diese anonyme Funktion wird folgendermaßen aufgerufen.
module
Hier wird auf dasModule
zuvor erstellte Objekt verwiesen.Wie wir in der Funktion sehen können,
exports
bezieht sich das formale Argument aufmodule.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.
Wenn wir es falsch machen ,
module.exports
zeigen wir immer noch auf das Objekt, das als Teil der Modulinstanz erstellt wurde.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.
quelle
exports = module.exports = {};
func()
@ Williams Antwort fehlschlägt!exports = module.exports = app;
der letzten Zeile des Codes hinzuzufügen . Es scheint, als würde dasmodule.exports
exportiert und wir werden es nie verwendenexports
, da es sich wieder in der letzten Zeile des Codes befindet. Also, warum fügen wir nicht einfach hinzumodule.exports = app;
Anfangs,
module.exports=exports
und dierequire
Funktion gibt zurück, auf die sich das Objektmodule.exports
bezieht.Wenn wir dem Objekt beispielsweise eine Eigenschaft hinzufügen , beziehen sich
exports.a=1
module.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.exports
ist der wahre Chef.quelle
exports
undmodule.exports
sind gleich, es sei denn, Sie weisenexports
innerhalb Ihres Moduls eine Neuzuweisung zu .Der einfachste Weg, darüber nachzudenken, besteht darin, zu denken, dass diese Zeile implizit oben in jedem Modul steht.
Wenn Sie innerhalb Ihres Moduls eine Neuzuweisung vornehmen
exports
, weisen Sie es innerhalb Ihres Moduls neu zu und es ist nicht mehr gleichmodule.exports
. Wenn Sie eine Funktion exportieren möchten, müssen Sie daher Folgendes tun:Wenn Sie einfach Ihre zugewiesen
function() { ... }
zuexports
, würden Sie werden Neuzuweisungexports
zu keinem längeren Punktmodule.exports
.Wenn Sie nicht
module.exports
jedes Mal auf Ihre Funktion verweisen möchten , können Sie Folgendes tun:Beachten Sie, dass dies
module.exports
das Argument ganz links ist.Das Anhängen von Eigenschaften an
exports
ist nicht dasselbe, da Sie es nicht neu zuweisen. Deshalb funktioniert dasquelle
JavaScript übergibt Objekte per Kopie einer Referenz
Es ist ein subtiler Unterschied, wie Objekte in JavaScript als Referenz übergeben werden.
exports
undmodule.exports
beide zeigen auf dasselbe Objekt.exports
ist eine Variable undmodule.exports
ein Attribut des Modulobjekts.Angenommen, ich schreibe so etwas:
exports
undmodule.exports
jetzt auf verschiedene Objekte zeigen. Durch Ändern von Exporten wird module.exports nicht mehr geändert.Wenn die Importfunktion prüft, wird
module.exports
es{b:12}
quelle
Ich mache nur einen Test, es stellt sich heraus, dass es im Modulcode von nodejs ungefähr so aussehen sollte:
damit:
1:
2:
3: aber in diesem Fall
quelle
module.exports
eine Art "Real-Deal", von dem der Knoten ausgeht, aber irgendwann müssen Sie alles hinzufügenexports
, esmodule.exports
sei denn, Sie verwenden einexports.namespace
(Fall 2 oben), was in diesem Fall so zu sein scheint Knoten hat ein 'extends(module.exports, exports);
Hinzufügen aller' Namespaces 'exports
zummodule.exports
Objekt ausgeführt? Mit anderen Worten, wenn Sie verwendenexports
, möchten Sie wahrscheinlich Eigenschaften festlegen?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:
quelle
Ich habe einige Tests durchlaufen und ich denke, dies könnte etwas Licht in das Thema bringen ...
app.js
::Versionen von
/routes/index.js
:Ich habe sogar neue Dateien hinzugefügt:
./routes/index.js
::./routes/not-index.js
::./routes/user.js
::Wir erhalten die Ausgabe "@routes {}"
./routes/index.js
::./routes/not-index.js
::./routes/user.js
::Wir erhalten die Ausgabe "@routes {fn: {}, user: {}}"
./routes/index.js
::./routes/not-index.js
::./routes/user.js
::Wir bekommen die Ausgabe "@routes {user: [Funktion: user]}" Wenn wir ändern
user.js
zu{ ThisLoadedLast: [Function: ThisLoadedLast] }
, wir die Ausgabe erhalten "@routes {ThisLoadedLast: [Funktion: ThisLoadedLast]}".Aber wenn wir modifizieren
./routes/index.js
..../routes/index.js
::./routes/not-index.js
::./routes/user.js
::... wir erhalten "@routes {fn: {fn: [Funktion: fn]}, ThisLoadedLast: {ThisLoadedLast: [Funktion: ThisLoadedLast]}}"
Daher würde ich vorschlagen, immer
module.exports
in 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
quelle
Dies zeigt, wie es
require()
in seiner einfachsten Form funktioniert, ein Auszug aus Eloquent JavaScriptProblem 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
exports
ihm erstellte Objekt als exportierten Wert verwendet.Lösung Stellen Sie Modulen eine andere Variable zur Verfügung,
module
bei der es sich um ein Objekt mit einer Eigenschaft handeltexports
. 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.quelle
Hier ist das Ergebnis von
Ebenfalls:
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.
quelle
// Erstens zeigen die Exporte und module.exports auf dasselbe leere Objekt
// Wenn Sie exp auf ein anderes Objekt zeigen, anstatt es auf ein anderes Objekt zu zeigen. Die md.exp ist leer Objekt {}
quelle
Aus den Dokumenten
Es ist nur eine Variable, die auf module.exports zeigt.
quelle
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
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
quelle
"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
quelle
module.exports
undexports
beide 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 derrequire
Anweisung in einem anderen Modul verwendet wird .exports
ist eine Verknüpfung, die für dasselbe bereitgestellt wird. Zum Beispiel:ist gleichbedeutend mit Schreiben:
Es ist also in Ordnung, solange Sie der
exports
Variablen keinen neuen Wert zuweisen . Wenn Sie so etwas tun:Wenn Sie ihm einen neuen Wert zuweisen,
exports
verweist er nicht mehr auf das exportierte Objekt und bleibt daher lokal für Ihr Modul.Wenn Sie vorhaben,
module.exports
dem 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:Die Website von Node.j hat eine sehr gute Erklärung dafür.
quelle
1.exports -> als Singleton-Dienstprogramm verwenden
2. Modul-Exporte -> als logische Objekte wie Service, Modell usw. Verwenden
quelle
Lassen Sie uns ein Modul mit zwei Möglichkeiten erstellen:
Einweg
Zweiter Weg
Und so wird require () das Modul integrieren.
Erster Weg:
Zweiter Weg
quelle
Ich glaube , sie wollen einfach nur klar sein , dass
module.exports
,exports
undnano
auf die gleiche Funktion - so dass Sie eine der Variablen verwenden , um die Funktion in der Datei aufzurufen.nano
bietet einen Kontext für die Funktionsweise der Funktion.exports
wird nicht exportiert (nurmodule.exports
wird), warum also auch das überschreiben?Der Kompromiss zwischen Ausführlichkeit begrenzt das Risiko zukünftiger Fehler, z. B. die Verwendung
exports
anstellemodule.exports
der Datei. Es wird auch klargestellt, dassmodule.exports
undexports
tatsächlich auf den gleichen Wert verweisen.module.exports
vs.exports
Solange Sie nicht neu zuweisen
module.exports
oderexports
(und stattdessen dem Objekt, auf das sich beide beziehen, Werte hinzufügen), haben Sie keine Probleme und können sicher verwendenexports
, 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.exports
etwas Bestimmtes sein (z. B. eine Funktion).Das Festlegen
exports
eines Nicht-Objekts ist wenig sinnvoll, da Sie esmodule.exports = exports
am Ende festlegen müssen, um es in anderen Dateien verwenden zu können.Warum
module.exports
einer 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:
helloWorld2.js:let sayHello = require('./helloWorld1'); sayHello.hello; // hello world
module.exports = () => console.log('hello world');
app2.js:
let sayHello = require('./helloWorld2'); sayHello; // hello world
quelle
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() => { ... }
dannrequire
überall in Ihrer Anwendung und Nutzung ...controller / user.js
erfordern in route.js zu verwenden:
quelle
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:
Beachten Sie, dass der erste Parameter
exports
ein leeres Objekt ist und der dritte Parametermodule
ein Objekt mit vielen Eigenschaften ist und eine der Eigenschaften benannt istexports
. Dasexports
kommt undmodule.exports
kommt. Das erstere ist ein variables Objekt, und das letztere ist eine Eigenschaft desmodule
Objekts.Innerhalb des Moduls macht Node.js dies am Anfang automatisch:
module.exports = exports
und kehrt schließlich zurückmodule.exports
.Sie können also sehen, dass eine Neuzuweisung eines Werts
exports
keine Auswirkung hatmodule.exports
. (Einfach weilexports
auf ein anderes neues Objekt zeigt, abermodule.exports
immer noch das alte enthältexports
)Wenn Sie jedoch die Eigenschaften von aktualisieren
exports
, hat dies sicherlich Auswirkungen aufmodule.exports
. Weil beide auf dasselbe Objekt zeigen.Beachten Sie auch, dass
module.exports
es fürexports
Updates bedeutungslos erscheint , wenn Sie einen anderen Wert neu zuweisen. Jede Aktualisierungexports
wird ignoriert, da siemodule.exports
auf ein anderes Objekt verweist.quelle
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
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.
Kopieren Sie diesen Code nach a.js.
Jetzt mit Knoten ausführen
Dies ist die Ausgabe
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."
quelle
Sie können
b
in Zeile 3 auf änderna
, die Ausgabe ist umgekehrt. Die Schlussfolgerung lautet:Also
module.exports = exports = nano = function database_module(cfg) {...}
ist gleichbedeutend mit:Angenommen, das Obige ist
module.js
, was von erforderlich istfoo.js
. Die Vorteile vonmodule.exports = exports = nano = function database_module(cfg) {...}
sind jetzt klar:In
foo.js
, damodule.exports
istrequire('./module.js')
:In
moduls.js
: Sie könnenexports
anstelle von verwendenmodule.exports
.Also, werden Sie , wenn beide glücklich sein
exports
undmodule.exports
auf die gleiche Sache zeigt.quelle