javascript - मॉड्यूल.एक्सपोर्ट्स बनाम नोड.जेएस में निर्यात




node.js commonjs (13)

मुझे Node.js मॉड्यूल में निम्न अनुबंध मिला है:

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

मुझे आश्चर्य है कि module.exports और exports बीच क्या अंतर है और दोनों का उपयोग यहां क्यों किया जाता है।


जावास्क्रिप्ट किसी संदर्भ की प्रतिलिपि द्वारा वस्तुओं को पास करता है

यह जावास्क्रिप्ट में संदर्भ द्वारा वस्तुओं को पारित करने के तरीके के साथ एक सूक्ष्म अंतर है।

exports और module.exports exports दोनों एक ही वस्तु को इंगित करते हैं। exports एक चर है और module.exports मॉड्यूल ऑब्जेक्ट की विशेषता है।

कहो मैं इस तरह कुछ लिखता हूं:

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

exports और module.exports exports अब विभिन्न वस्तुओं को इंगित करते हैं। निर्यात को संशोधित करना अब मॉड्यूल.एक्सपोर्ट को संशोधित नहीं करता है।

जब आयात फ़ंक्शन module.exports निरीक्षण करता है। module.exports करता है {b:12}


  1. module.exports और exports दोनों एक ही function database_module(cfg) {...} module.exports 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"
    

    आप लाइन 3 पर b को बदल सकते हैं, आउटपुट रिवर्स है। निष्कर्ष यह है:

    a और b स्वतंत्र हैं।

  2. तो module.exports = exports = nano = function database_module(cfg) {...} के बराबर है:

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

    मान लिया गया है ऊपर module.js , जो foo.js द्वारा आवश्यक है। module.exports = exports = nano = function database_module(cfg) {...} अब स्पष्ट हैं:

    • foo.js , चूंकि module.exports की require('./module.js') :

      var output = require('./modules.js')();
      
    • moduls.js : आप module.exports बजाय exports उपयोग कर सकते हैं।

इसलिए, यदि आप दोनों exports और module.exports एक ही चीज़ को इंगित करते हैं तो आप खुश होंगे।


1. निर्यात -> सिंगलटन उपयोगिता के रूप में उपयोग करें
2. मॉड्यूल-निर्यात -> लॉजिकल ऑब्जेक्ट्स जैसे सेवा, मॉडल इत्यादि के रूप में उपयोग करें


आइए दो मॉड्यूल के साथ एक मॉड्यूल बनाएं:

एक रास्ता

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

module.exports = aa;

दूसरा तरीका

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

और इस प्रकार मॉड्यूल को एकीकृत करने की आवश्यकता है ()

पहला तरीका:

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

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

    return module.exports;
}

दूसरा तरीका

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

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

    return module.exports;
}

नोड जेएस module.js फ़ाइल में मॉड्यूल.लोड सिस्टम चलाने के लिए उपयोग किया जाता है। हर बार जब नोड फ़ाइल निष्पादित करता है तो यह आपके जेएस फ़ाइल सामग्री को अनुवर्ती रूप में लपेटता है

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

आपके जेएस स्रोत कोड के अंदर इस रैपिंग की वजह से आप निर्यात, आवश्यकता, मॉड्यूल इत्यादि तक पहुंच सकते हैं .. इस दृष्टिकोण का उपयोग किया जाता है क्योंकि जेएस फ़ाइल पर दूसरे में कार्यक्षमताएं लिखने का कोई अन्य तरीका नहीं है।

फिर code ++ का उपयोग करके इस लपेटा फ़ंक्शन निष्पादित करें। उस समय निर्यात कार्य जो इस समारोह में पारित हो जाएगा।

आप इस फ़ंक्शन पैरामीटर निर्यात और मॉड्यूल के अंदर देख सकते हैं। वास्तव में निर्यात मॉड्यूल कन्स्ट्रक्टर फ़ंक्शन का एक सार्वजनिक सदस्य है।

निम्नलिखित कोड देखें

इस कोड को 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();

इस कोड को 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');}

अब नोड का उपयोग कर चलाएं

यह आउटपुट है

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

निर्यात [ऑब्जेक्ट ऑब्जेक्ट] है

foo का object.keys: नाम कार्य () {console.log ('मॉड्यूल निर्यात के लिए फ़ंक्शन')} मॉड्यूल निर्यात में फ़ंक्शन है

अब a.js में टिप्पणी की गई रेखा को हटा दें और उस पंक्ति के ऊपर की रेखा पर टिप्पणी करें और b.js की अंतिम पंक्ति को हटाएं और चलाएं।

जावास्क्रिप्ट दुनिया में आप पैरामीटर के रूप में पारित ऑब्जेक्ट को पुन: असाइन नहीं कर सकते हैं, लेकिन फ़ंक्शन के सार्वजनिक सदस्य को तब बदल सकते हैं जब उस फ़ंक्शन की ऑब्जेक्ट किसी अन्य फ़ंक्शन पर पैरामीटर के रूप में सेट हो

की याद हैं

मॉड्यूल.एक्सपोर्ट्स का उपयोग करें और केवल तभी जब आप एक कीवर्ड प्राप्त करना चाहते हैं तो आप एक कीवर्ड प्राप्त करना चाहते हैं। उपरोक्त उदाहरण में हम var foo = आवश्यकता (a.js); आप देख सकते हैं कि हम फ़ू को फ़ंक्शन के रूप में कॉल कर सकते हैं;

इस प्रकार नोड दस्तावेज इसे समझाता है "निर्यात वस्तु मॉड्यूल सिस्टम द्वारा बनाई गई है। कभी-कभी यह स्वीकार्य नहीं है, कई लोग चाहते हैं कि उनका मॉड्यूल कुछ वर्ग का उदाहरण हो। ऐसा करने के लिए मॉड्यूल.एक्सपोर्ट्स को वांछित निर्यात ऑब्जेक्ट असाइन करें।"


प्रारंभ में, module.exports=exports , और require फ़ंक्शन ऑब्जेक्ट module.exports देता है। module.exports संदर्भ है।

यदि हम ऑब्जेक्ट में संपत्ति जोड़ते हैं , तो export.a exports.a=1 कहें, फिर मॉड्यूल.एक्सपोर्ट्स और निर्यात अभी भी एक ही ऑब्जेक्ट को संदर्भित करते हैं। इसलिए यदि हम एक चर को मॉड्यूल की आवश्यकता और असाइन करते हैं, तो चर के पास एक संपत्ति है और इसका मान 1 है;

लेकिन अगर हम उनमें से एक को ओवरराइड करते हैं, उदाहरण के लिए, exports=function(){} , तो वे अब अलग हैं: निर्यात एक नई वस्तु को संदर्भित करता है और module.exports मूल ऑब्जेक्ट को संदर्भित करता है। और अगर हमें फ़ाइल की आवश्यकता है, तो यह नई ऑब्जेक्ट नहीं लौटाएगा, क्योंकि मॉड्यूल.एक्सपोर्ट नई ऑब्जेक्ट का संदर्भ नहीं देता है।

मेरे लिए, मैं नई संपत्ति जोड़ना जारी रखूंगा, या दोनों को एक नई वस्तु में ओवरराइड कर दूंगा। बस एक ओवरराइड सही नहीं है। और ध्यान रखें कि module.exports वास्तविक मालिक है।


मैं कुछ परीक्षणों के माध्यम से चला गया और मुझे लगता है कि यह इस विषय पर कुछ प्रकाश डाल सकता है ...

app.js :

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

/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] }"

मैंने नई फाइलें भी जोड़ दीं:

./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(){};

हमें उत्पादन "@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(){};

हमें आउटपुट मिलता है "@routes {fn: {}, उपयोगकर्ता: {}}"

./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(){};

हमें "@routes {उपयोगकर्ता: [फंक्शन: उपयोगकर्ता]} आउटपुट मिलता है" अगर हम user.js को { ThisLoadedLast: [Function: ThisLoadedLast] } , तो हमें आउटपुट मिलता है "@routes {thisLoadedLast: [Function: ThisLoadedLast]} "।

लेकिन अगर हम ./routes/index.js संशोधित ./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(){};

... हमें "@ रूट्स {एफएन: {एफएन: [फंक्शन: एफएन]}, यह लोडेडस्टास्ट मिलता है: {यह लोडेडलास्ट: [फंक्शन: यह लोडेडलास्ट]}}"

इसलिए मैं हमेशा आपकी मॉड्यूल परिभाषाओं में module.exports का उपयोग करने का सुझाव module.exports

मैं पूरी तरह से समझ नहीं पा रहा हूं कि आंतरिक रूप से नोड के साथ क्या चल रहा है, लेकिन अगर आप इस बारे में अधिक समझ सकते हैं तो कृपया टिप्पणी करें क्योंकि मुझे यकीन है कि इससे मदद मिलती है।

- हैप्पी कोडिंग


मैं बस कुछ परीक्षण करता हूं, यह पता चला है कि, नोडजेस के मॉड्यूल कोड के अंदर, इसे कुछ ऐसा करना चाहिए:

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

इसलिए:

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: लेकिन, इस मामले में जबकि

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)

यह दिखाता है कि कैसे require() अपने सरलतम रूप में काम करता है, जो एलोक्वेंट जावास्क्रिप्ट से उद्धृत है

समस्या मॉड्यूल के लिए निर्यात ऑब्जेक्ट के अलावा किसी अन्य मूल्य को सीधे निर्यात करने के लिए संभव नहीं है, जैसे फ़ंक्शन। उदाहरण के लिए, एक मॉड्यूल केवल उस ऑब्जेक्ट प्रकार के निर्माता का निर्यात करना चाहता है जो इसे परिभाषित करता है। अभी, यह ऐसा नहीं कर सकता क्योंकि हमेशा exports ऑब्जेक्ट का उपयोग करता है जो इसे निर्यात मूल्य के रूप में बनाता है।

समाधान एक अन्य चर, मॉड्यूल के साथ मॉड्यूल प्रदान करें, जो एक वस्तु है जिसमें संपत्ति exports । यह संपत्ति प्रारंभ में आवश्यक वस्तु के आधार पर खाली वस्तु पर इंगित करती है लेकिन कुछ और निर्यात करने के लिए किसी अन्य मूल्य के साथ ओवरराइट की जा सकती है।

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

हालांकि प्रश्न का उत्तर दिया गया है और बहुत पहले स्वीकार किया गया है, मैं बस अपने 2 सेंट साझा करना चाहता हूं:

आप कल्पना कर सकते हैं कि आपकी फ़ाइल की शुरुआत में कुछ ऐसा है (केवल स्पष्टीकरण के लिए):

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

तो जो भी आप करते हैं, बस ध्यान रखें कि module.exports और exports नहीं आपके मॉड्यूल से वापस आ जाएंगे जब आपको उस मॉड्यूल को कहीं और से आवश्यकता होगी।

तो जब आप कुछ ऐसा करते हैं:

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

आप उस ऑब्जेक्ट पर 2 फ़ंक्शन 'ए' और 'बी' जोड़ रहे हैं जिस पर मॉड्यूल.एक्सपोर्ट्स भी इंगित करता है, इसलिए रिटर्निंग परिणाम का प्रकार एक object : { a: [Function], b: [Function] }

बेशक यह वही परिणाम है यदि आप exports बजाय इस उदाहरण में module.exports का उपयोग कर रहे हैं।

यह वह मामला है जहां आप अपने मॉड्यूल.पोर्ट्स को निर्यात किए गए मानों के कंटेनर की तरह व्यवहार करना चाहते हैं। हालांकि, यदि आप केवल एक कन्स्ट्रक्टर फ़ंक्शन निर्यात करना चाहते हैं तो module.exports या exports का उपयोग करने के बारे में आपको कुछ पता होना चाहिए; (याद रखें कि मॉड्यूल.एक्सपोर्ट वापस लौटाए जाएंगे जब आपको कुछ चाहिए, निर्यात नहीं होगा)।

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

अब टाइपिंग रिटर्निंग परिणाम 'function' और आपको इसकी आवश्यकता हो सकती है और तुरंत इस तरह का आह्वान किया जा सकता है:
var x = require('./file1.js')(); क्योंकि आप रिटर्निंग परिणाम को फ़ंक्शन के रूप में ओवरराइट करते हैं।

हालांकि, exports का उपयोग करके आप कुछ इस तरह उपयोग नहीं कर सकते हैं:

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

चूंकि exports साथ, संदर्भ उस ऑब्जेक्ट को 'पॉइंट' नहीं करता है जहां module.exports पॉइंट्स हैं, इसलिए exports और module.exports बीच कोई संबंध नहीं है। इस मामले में module.exports अभी भी खाली ऑब्जेक्ट को इंगित करता है {} जो वापस कर दिया जाएगा।

किसी अन्य विषय से स्वीकृत उत्तर में भी मदद करनी चाहिए: जावास्क्रिप्ट संदर्भ द्वारा पास करता है?


exports और module.exports समान हैं जब तक आप अपने मॉड्यूल के भीतर exports को पुन: असाइन नहीं करते।

इसके बारे में सोचने का सबसे आसान तरीका यह है कि यह लाइन प्रत्येक मॉड्यूल के शीर्ष पर निहित है।

var exports = module.exports = {};

यदि, आपके मॉड्यूल के भीतर, आप exports को फिर से सौंप देते हैं, तो आप इसे अपने मॉड्यूल के भीतर फिर से सौंप देते हैं और यह अब module.exports बराबर नहीं है। यही कारण है कि, यदि आप एक फ़ंक्शन निर्यात करना चाहते हैं, तो आपको यह करना होगा:

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

यदि आपने exports लिए अपने function() { ... } को असाइन किया है, तो आप module.exports को इंगित करने के लिए exports को पुन: असाइन करेंगे।

यदि आप हर बार module.exports द्वारा अपने फ़ंक्शन को संदर्भित नहीं करना चाहते हैं, तो आप यह कर सकते हैं:

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

ध्यान दें कि module.exports बाईं ओर सबसे अधिक तर्क है।

exports लिए संपत्ति संलग्न करना वही नहीं है क्योंकि आप इसे पुन: असाइन नहीं कर रहे हैं। यही कारण है कि यह काम करता है

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

module.exports सेट करने से module.exports फ़ंक्शन को required होने पर फ़ंक्शन की तरह कॉल करने की अनुमति module.exports । बस exports को सेट करने से फ़ंक्शन को निर्यात करने की अनुमति नहीं मिलती क्योंकि नोड ऑब्जेक्ट module.exports निर्यात करता है। निर्यात संदर्भ। निम्न कोड उपयोगकर्ता को फ़ंक्शन को कॉल करने की अनुमति नहीं देगा।

module.js

निम्नलिखित काम नहीं करेगा।

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

module.exports सेट होने पर निम्नलिखित काम करेंगे।

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

कंसोल

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

मूल रूप से node.js उस ऑब्जेक्ट को exports नहीं करता है जो वर्तमान में संदर्भ निर्यात करता है, लेकिन मूल रूप से संदर्भों के निर्यात के गुणों का exports । हालांकि Node.js ऑब्जेक्ट module.exports निर्यात करता है। निर्यात संदर्भ, जिससे आप इसे फ़ंक्शन की तरह कॉल कर सकते हैं।

दूसरा कम से कम महत्वपूर्ण कारण

उन्होंने यह सुनिश्चित करने के लिए module.exports और exports दोनों सेट किए हैं कि exports पूर्व निर्यात किए गए ऑब्जेक्ट का संदर्भ नहीं दे रहा है। आप दोनों को शॉर्टेंड के रूप में exports उपयोग करके और बाद में सड़क पर संभावित बग से बचने के लिए सेट करें।

module.exports.prop = true exports.prop = true बजाय module.exports.prop = true का उपयोग करना अक्षर सहेजता है और भ्रम से बचाता है।


var a = {},md={};

// सबसे पहले, निर्यात और मॉड्यूल.एक्सपोर्ट एक ही खाली वस्तु को इंगित करते हैं

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

exp.attr = "change";

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

// यदि आप अन्य ऑब्जेक्ट की ओर इशारा करते हैं तो यह अन्य ऑब्जेक्ट की ओर इशारा करते हैं। Md.exp खाली ऑब्जेक्ट होगा {}

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

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

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




commonjs