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




node.js commonjs (16)

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

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

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


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

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

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

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


मैंने यह लिंक उपर्युक्त प्रश्न का उत्तर देने के लिए उपयोगी पाया।

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

अन्य पदों में जोड़ने के लिए नोड में मॉड्यूल सिस्टम करता है

var exports = module.exports 

अपना कोड निष्पादित करने से पहले। तो जब आप निर्यात करना चाहते हैं = foo, तो आप शायद मॉड्यूल करना चाहते हैं। निर्यात = निर्यात = foo लेकिन export.foo = foo का उपयोग करना ठीक होना चाहिए


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

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)

मैनिंग प्रकाशन से एक्शन बुक में node.js में नोड मॉड्यूल के बारे में लिखा गया एक अच्छा वर्णन यहां दिया गया है।
अंत में आपके आवेदन में निर्यात किया जाता है मॉड्यूल.एक्सपोर्ट्स है।
निर्यात मॉड्यूल.एक्सपोर्ट्स के वैश्विक संदर्भ के रूप में स्थापित किया जाता है, जिसे प्रारंभ में एक खाली वस्तु के रूप में परिभाषित किया जाता है जिसे आप गुण जोड़ सकते हैं। तो export.myFunc मॉड्यूल . exports.myFunc के लिए सिर्फ shorthand है।

नतीजतन, यदि निर्यात किसी और चीज पर सेट किया गया है, तो यह मॉड्यूल.एक्सपोर्ट्स और निर्यात के बीच संदर्भ को तोड़ देता है । चूंकि मॉड्यूल.एक्सपोर्ट्स वास्तव में निर्यात किया जाता है, निर्यात अब अपेक्षित काम नहीं करेगा-यह मॉड्यूल का संदर्भ नहीं देता है। निर्यात अब और नहीं है। यदि आप उस लिंक को बनाए रखना चाहते हैं, तो आप निम्नानुसार मॉड्यूल.एक्सपोर्ट संदर्भ निर्यात कर सकते हैं:

module.exports = exports = db;

"यदि आप अपने मॉड्यूल के निर्यात की जड़ को एक फ़ंक्शन (जैसे कि कन्स्ट्रक्टर) होना चाहते हैं या यदि आप एक समय में एक संपत्ति बनाने के बजाय एक असाइनमेंट में एक पूर्ण ऑब्जेक्ट निर्यात करना चाहते हैं, तो इसे मॉड्यूल.एक्सपोर्ट्स के बजाय असाइन करें निर्यात। " - http://nodejs.org/api/modules.html


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 का उपयोग करना अक्षर सहेजता है और भ्रम से बचाता है।


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

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

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

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

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

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

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


इसका नतीजा यहां है

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

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

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

इसके अलावा:

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

//YES

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


हालांकि प्रश्न का उत्तर दिया गया है और बहुत पहले स्वीकार किया गया है, मैं बस अपने 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 अभी भी खाली ऑब्जेक्ट को इंगित करता है {} जो वापस कर दिया जाएगा।

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


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

एक रास्ता

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

यह दिखाता है कि कैसे 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);

मूल रूप से उत्तर वास्तव में तब होता है जब require बयान के माध्यम से एक मॉड्यूल की आवश्यकता require है। मान लें कि यह पहली बार मॉड्यूल की आवश्यकता है।

उदाहरण के लिए:

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

file1.js की सामग्री:

module.exports = '123';

जब उपर्युक्त कथन निष्पादित किया जाता है, तो Module ऑब्जेक्ट बनाया जाता है। इसका कन्स्ट्रक्टर फ़ंक्शन है:

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

जैसा कि आप देखते हैं कि प्रत्येक मॉड्यूल ऑब्जेक्ट में नाम exports साथ एक संपत्ति है। अंततः require हिस्से के रूप में यह वापस किया जाता require

आवश्यकता का अगला चरण फ़ाइल 1.js की सामग्री को नीचे दिए गए अज्ञात फ़ंक्शन में लपेटना है:

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

और यह अज्ञात फ़ंक्शन निम्न तरीके से आक्रमण किया जाता है, यहां Module पहले बनाए गए Module ऑब्जेक्ट को संदर्भित करता है।

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

जैसा कि हम समारोह के अंदर देख सकते हैं, exports औपचारिक तर्क module.exports को संदर्भित करता है। संक्षेप में यह मॉड्यूल प्रोग्रामर को प्रदान की जाने वाली सुविधा है।

हालांकि इस सुविधा को देखभाल के साथ प्रयोग करने की आवश्यकता है। किसी भी मामले में यदि निर्यात के लिए एक नई वस्तु को सौंपने का प्रयास करना सुनिश्चित करता है तो हम इसे इस तरह से करते हैं।

exports = module.exports = {};

यदि हम इसे गलत तरीके से करते हैं , तो module.exports अभी भी मॉड्यूल इंस्टेंस के हिस्से के रूप में बनाए गए ऑब्जेक्ट पर इंगित करेगा।

exports = {};

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


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


docs

निर्यात चर मॉड्यूल के फ़ाइल-स्तरीय दायरे में उपलब्ध है, और मॉड्यूल का मूल्यांकन करने से पहले मॉड्यूल.एक्सपोर्ट का मान असाइन किया गया है।

यह शॉर्टकट की अनुमति देता है, ताकि module.exports.f = ... को export.f = .... के रूप में अधिक संक्षेप में लिखा जा सके। हालांकि, किसी भी चर की तरह, यदि निर्यात के लिए कोई नया मान सौंपा गया है, तो यह है मॉड्यूल के लिए बाध्य नहीं है। निर्यात:

यह मॉड्यूल.एक्सपोर्ट्स को इंगित करने वाला एक चर है।


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.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); आप देख सकते हैं कि हम फ़ू को फ़ंक्शन के रूप में कॉल कर सकते हैं;

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





commonjs