2013-05-05 8 views
174

Auf dieser Seite (http://docs.nodejitsu.com/articles/getting-started/what-is-require) heißt es: "Wenn Sie das exports-Objekt auf eine Funktion oder ein neues Objekt setzen möchten, müssen Sie verwenden das Modul.exports Objekt. "Unterschied zwischen "module.exports" und "exports" im CommonJs-Modul System

Meine Frage ist warum.

// right 
module.exports = function() { 
    console.log("hello world") 
} 
// wrong 
exports = function() { 
    console.log("hello world") 
} 

I console.logged das Ergebnis (result=require(example.js)) und der erste ist [Function] die zweite {} ist.

Könnten Sie bitte den Grund dafür erklären? Ich habe den Beitrag hier gelesen: module.exports vs exports in Node.js. Es ist hilfreich, erklärt aber nicht den Grund, warum es so entworfen wurde. Wird es ein Problem geben, wenn die Referenz der Exporte direkt zurückgegeben wird?

+4

Verwenden Sie immer 'module.exports'. –

+0

Ich denke, die oben genannten Ratschläge können dieses Problem vermeiden. –

+0

@GabrielLlamas Warum verwenden viele Pakete nur 'exports', zum Beispiel https://github.com/tj/consolidate.js/blob/master/lib/consolidate.js? – CodyBugstein

Antwort

421

module ist ein einfaches JavaScript-Objekt mit einer exports Eigenschaft. exports ist eine einfache JavaScript-Variable, die zufällig auf module.exports gesetzt ist. Am Ende Ihrer Datei wird node.js im Prinzip module.exports an die require-Funktion zurückgeben. Eine vereinfachte Art und Weise eine JS-Datei in Knoten betrachten könnte dies sein:

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

// your code 

return module.exports; 

Wenn Sie eine Immobilie auf exports gesetzt, wie exports.a = 9;, die module.exports.a auch eingestellt werden, da Objekte um als Referenzen in JavaScript übergeben werden, was bedeutet, Wenn Sie mehrere Variablen auf dasselbe Objekt setzen, sind sie alle das gleiche Objekt; also dann exports und module.exports sind das gleiche Objekt.
Wenn Sie jedoch exports auf etwas Neues setzen, wird es nicht mehr auf module.exports gesetzt, so dass exports und module.exports nicht mehr das gleiche Objekt sind.

+6

Richtig, es sind nur Grundlagen der Referenztypen. –

+4

Warum? Warum kann man das hier nur lesen? Dies sollte ein Slogan für jedes modulare Java Script sein. Danke –

13

Renes Antwort über die Beziehung zwischen exports und module.exports ist ziemlich klar, es dreht sich alles um Javascript-Referenzen. Ich will nur noch hinzufügen:

Wir sehen dies in vielen Knotenmodule:

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

Dies wird sicherstellen, dass selbst wenn wir module.exports geändert, wir immer noch die Exporte, indem diese beiden Variablen verwenden auf das gleiche Objekt zeigen.

+0

Ich wurde mit dieser Erklärung verwirrt, nett zu erarbeiten? – GuyFreakz

+3

@GuyFreakz Ich bin mir nicht sicher, ob dies zu Ihrer Verwirrung führt, aber 'module.exports' und' exports' sind nur separate Variablen, die initialisiert wurden, um auf dasselbe Objekt zu verweisen. Wenn Sie ändern, was eine Variable referenziert, verweisen die beiden Variablen nicht mehr auf dasselbe. Die obige Codezeile stellt sicher, dass beide Variablen für dasselbe neue Objekt initialisiert werden. –

+0

Ein tatsächlicher Anwendungsfall, den alle anderen auf @fengshuo verpasst haben. Vielen Dank! –

15

Auch eine Dinge, die helfen können, verstehen:

math.js

this.add = function (a, b) { 
    return a + b; 
}; 

Client.js

var math = require('./math'); 
console.log(math.add(2,2); // 4; 

Große, in diesem Fall:

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

Also standardmäßig "this" i s entspricht tatsächlich module.exports.

Wenn Sie jedoch Ihre Implementierung ändern:

math.js

var add = function (a, b) { 
    return a + b; 
}; 

module.exports = { 
    add: add 
}; 

In diesem Fall wird es funktionieren, aber „dieses“ module.exports nicht gleich mehr, weil ein neues Objekt erstellt wurde.

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

Und nun, was durch die erfordern zurückgegeben werden wird, was in dem module.exports wurde definiert, das nicht oder Ausfuhr mehr.

Eine andere Möglichkeit, es zu tun wäre:

math.js

module.exports.add = function (a, b) { 
    return a + b; 
}; 

Oder:

math.js

exports.add = function (a, b) { 
    return a + b; 
}; 
22

Antwort des Renee ist gut erklärt. Ergänzung zur Antwort mit einem Beispiel:

Knoten macht eine Menge Dinge zu Ihrer Datei und eine der wichtigsten ist WRAPPING Ihre Datei. Innerhalb von nodejs wird der Quellcode "module.exports" zurückgegeben. Lass uns einen Schritt zurückgehen und den Wrapper verstehen. Angenommen, Sie haben

greet.js

var greet = function() { 
    console.log('Hello World'); 
}; 

module.exports = greet; 

der obige Code wird als IIFE gewickelt (sofort aufgerufen Funktion Expression) innerhalb NodeJS Quellcode wie folgt:

(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 

und die obige Funktion wird aufgerufen, (.apply()) und zurückgegebene module.exports. Zu diesem Zeitpunkt zeigt module.exports und exports auf den gleichen Verweis.

Nun stellen Sie greet.js als

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

der Ausgang

[Function] 
{} 

der Grund sein wird, neu schreiben: module.exports ein leeres Objekt ist. Wir haben nichts auf module.exports gesetzt, sondern exports = function() ..... in new greet.js. Also, module.exports ist leer.

Technisch Exporte und module.exports sollten auf die gleiche Referenz verweisen (das ist korrekt !!). Aber wir verwenden "=", wenn wir export Funktionen() ... zuweisen, wodurch ein anderes Objekt im Speicher erzeugt wird. Modul.exports und exports produzieren also unterschiedliche Ergebnisse. Wenn es um Exporte geht, können wir es nicht überschreiben.

Nun stellen Sie neu zu schreiben (dies wird als Mutation) greet.js (bezogen auf Renee Antwort) als

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

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

der Ausgang

{ a: [Function] } 
{ a: [Function] } 

werden Sie sehen: module.exports und exports zeigen auf dieselbe Referenz, die eine Funktion ist. Wenn Sie eine Eigenschaft für Exporte festlegen, wird sie auf module.exports festgelegt, da Objekte in JS als Verweis übergeben werden.

Fazit ist immer module.exports verwenden, um Verwirrung zu vermeiden. Hoffe, das hilft. Happy coding :)

Verwandte Themen