आम मॉड्यूल प्रणाली में "मॉड्यूल.एक्सपोर्ट" और "निर्यात" के बीच अंतर


276

इस पृष्ठ पर ( http://docs.nodejitsu.com/articles/getting-started/what-is-require ), यह बताता है कि "यदि आप किसी फ़ंक्शन या नई ऑब्जेक्ट में निर्यात ऑब्जेक्ट सेट करना चाहते हैं, तो आपको करना होगा मॉड्यूल .exports ऑब्जेक्ट का उपयोग करें। "

मेरा सवाल यह है कि

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

मैंने रिजल्ट ( result=require(example.js)) को सांत्वना दी। और पहला [Function]वाला दूसरा है {}

क्या आप इसके पीछे का कारण बता सकते हैं? मैं यहाँ पोस्ट पढ़ता हूँ: Node.js में मॉड्यूल बनाम निर्यात । यह सहायक है, लेकिन इसका कारण नहीं बताता है कि इसे इस तरह से क्यों बनाया गया है। यदि निर्यात का संदर्भ सीधे लौटाया जाएगा तो क्या कोई समस्या होगी?


11
हमेशा उपयोग करें module.exports
गेब्रियल ललामास

1
मुझे लगता है कि उपरोक्त सलाह के बाद इस समस्या से बचने की अनुमति मिलती है।
विटालि कोर्साकोव

@GabrielLlamas इसलिए कई पैकेज सिर्फ exportsउदाहरण के लिए, github.com/tj/consolidate.js/blob/master/lib/consolidate.js के लिए उपयोग क्यों करते हैं ?
कॉडीबगस्टीन

3
@Imray आप हमेशा का उपयोग करते हैं module.exports, तो आप कभी नहीं गलत हो जाएगा, लेकिन आप उपयोग कर सकते हैं exportsयदि आप डिफ़ॉल्ट निर्यात वस्तु, कि है, अगर आप बस इस तरह के गुण देते जगह नहीं कर रहे हैं: var foo = require('foo').foo। इस fooसंपत्ति को इस तरह निर्यात किया जा सकता है: exports.foo = ...और निश्चित रूप से भी module.exports। यह एक व्यक्तिगत पसंद है लेकिन मैं वर्तमान में module.exportsऔर exportsउचित रूप से उपयोग कर रहा हूं ।
गेब्रियल लामास

मैं Export.myFunc = function () {} को प्राथमिकता देता हूं, इसलिए मुझे फ़ाइल के निचले भाग में निर्यात की सूची बनाए रखने की आवश्यकता नहीं है। जब आप ES6 में घोषणा करते हैं तो यह निर्यात के सामान्य अभ्यास के करीब महसूस होता है।
SacWebDeveloper

जवाबों:


624

moduleएक exportsसंपत्ति के साथ एक सादे जावास्क्रिप्ट वस्तु है । exportsएक सादा जावास्क्रिप्ट वैरिएबल है जो सेट होने के लिए होता है module.exports। आपकी फ़ाइल के अंत में, नोड.जेएस मूल रूप module.exportsसे requireफ़ंक्शन में 'वापस' आएगा । नोड में JS फाइल देखने का एक सरल तरीका यह हो सकता है:

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

// your code

return module.exports;

यदि आप एक संपत्ति सेट करते हैं exports, जैसे exports.a = 9;कि, वह भी सेट करेगा module.exports.aक्योंकि ऑब्जेक्ट्स को जावास्क्रिप्ट में संदर्भ के रूप में चारों ओर से पारित किया जाता है, जिसका अर्थ है कि यदि आप एक ही वस्तु के लिए कई चर सेट करते हैं , तो वे सभी एक ही वस्तु हैं; तो फिर exportsऔर module.exportsएक ही वस्तु है।
लेकिन अगर आप exportsकुछ नया सेट करते हैं module.exports, तो यह अब सेट नहीं किया जाएगा , इसलिए exportsऔर module.exportsअब एक ही वस्तु नहीं हैं।


11
ठीक है, यह केवल संदर्भ प्रकारों की मूल बातें है।
विटालि कोर्साकोव

18
क्यों!? क्यों कोई इसे केवल यहां पढ़ सकता है। यह हर मॉड्यूलर javaScript के लिए टैगलाइन होनी चाहिए। धन्यवाद
lima_fil

8
खूबसूरती से समझाया!
आकाश वर्मा

3
कमाल, बेहतरीन जवाब !!
जॉन

5
महान व्याख्या। इसके लिए दस्तावेज में module.exportsयह भी बताया गया है: nodejs.org/api/modules.html#modules_module_exports
ब्रायन मोरारी

52

रेनी का जवाब अच्छी तरह से समझाया गया है। एक उदाहरण के साथ जवाब में जोड़ना:

नोड आपकी फ़ाइल के लिए बहुत सी चीज़ें करता है और महत्वपूर्ण में से एक है आपकी फ़ाइल की प्रतिलिपि बनाना। नोडजस सोर्स कोड के अंदर "मॉड्यूल.एक्सपोर्ट्स" वापस आ गया है। आओ हम एक कदम पीछे हटें और रैपर को समझें। मान लो तुम्हारे पास है

greet.js

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

module.exports = greet;

उपर्युक्त कोड निम्न प्रकार से नोड्स के स्रोत कोड के अंदर IIFE (तत्काल इनवॉइस फंक्शन एक्सप्रेशन) के रूप में लिपटा हुआ है:

(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

और उपरोक्त फ़ंक्शन (.apply ()) और वापस लौटे मॉड्यूल.exports है। इस समय मॉड्यूल.एक्सपोर्ट और निर्यात एक ही संदर्भ की ओर इशारा करते हैं।

अब, आप के रूप में फिर से बधाई लिखो

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

आउटपुट होगा

[Function]
{}

इसका कारण है: मॉड्यूल.एक्सपोर्ट एक खाली वस्तु है। हमने मॉड्यूल.exports के लिए कुछ भी सेट नहीं किया था, बल्कि हम नए शुभकामना में निर्यात = फ़ंक्शन () ..... सेट करते हैं। इसलिए, मॉड्यूल .exports खाली है।

तकनीकी रूप से निर्यात और मॉड्यूल.एक्सपोर्ट्स को एक ही संदर्भ (यानी सही !!) को इंगित करना चाहिए। लेकिन हम फ़ंक्शन का उपयोग करते समय "=" का उपयोग करते हैं () .... निर्यात करने के लिए, जो मेमोरी में एक और ऑब्जेक्ट बनाता है। इसलिए, मॉड्यूल। निर्यात और निर्यात अलग परिणाम देते हैं। जब निर्यात की बात आती है तो हम इसे ओवरराइड नहीं कर सकते।

अब, आपको फिर से लिखने की कल्पना करें (इसे म्यूटेशन कहा जाता है)

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

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

आउटपुट होगा

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

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

निष्कर्ष हमेशा भ्रम से बचने के लिए मॉड्यूल .exports का उपयोग करें। उम्मीद है की यह मदद करेगा। मुबारक कोडिंग :)


यह भी, एक सुंदर व्यावहारिक उत्तर है और @ गोटो-बस-स्टॉप का उत्तर पूरक है। :)
वरुण

23

इसके अलावा, एक चीज जो समझने में मदद कर सकती है:

math.js

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

client.js

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

इस मामले में महान,

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

इस प्रकार, डिफ़ॉल्ट रूप से, "यह" वास्तव में मॉड्यूल.एक्सपोर्ट के बराबर है।

हालाँकि, यदि आप अपना कार्यान्वयन इसमें बदलते हैं:

math.js

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

module.exports = {
    add: add
};

इस मामले में, यह ठीक काम करेगा, हालांकि, "यह" अब मॉड्यूल.एक्सपोर्ट के बराबर नहीं है, क्योंकि एक नई वस्तु बनाई गई थी।

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

और अब, क्या आवश्यकता द्वारा लौटाया जाएगा जो मॉड्यूल के अंदर परिभाषित किया गया था। निर्यात, यह या निर्यात नहीं, अब।

इसे करने का एक और तरीका होगा:

math.js

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

या:

math.js

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

15

रेने के बीच के रिश्ते के बारे में जवाब exportsऔर module.exportsस्पष्ट है, यह सभी जावास्क्रिप्ट संदर्भों के बारे में है। बस उसे जोड़ना चाहते हैं:

हम इसे कई नोड मॉड्यूल में देखते हैं:

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

यह सुनिश्चित करेगा कि भले ही हमने मॉड्यूल.एक्सपोर्ट्स को बदल दिया है, हम अभी भी उन दो चर को एक ही वस्तु पर बनाकर निर्यात का उपयोग कर सकते हैं।


मैं इस स्पष्टीकरण से भ्रमित हो गया, विस्तृत करने के लिए?
गाइफ्रीकज

6
@GuyFreakz मुझे यकीन है कि अगर यह आपके भ्रम को बोलता है नहीं कर रहा हूँ, लेकिन module.exportsऔर exportsसिर्फ अलग चर, एक ही वस्तु के संदर्भ के लिए प्रारंभ कर रहे हैं। यदि आप एक चर संदर्भ को बदलते हैं, तो दो चर अब एक ही चीज को संदर्भित नहीं करते हैं। ऊपर दिए गए कोड की लाइन यह सुनिश्चित करती है कि दोनों चर एक ही नई वस्तु से आरंभ किए गए हैं।
एंड्रयू पामर

एक वास्तविक उपयोग का मामला जो बाकी सब @ फेंगशुओ से छूट गया। धन्यवाद!
आकाश वर्मा

0

myTest.js

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

exports.put = function () {};

console.log(module.exports)
// output: { get: [Function], put: [Function] }

exportsऔर module.exportsएक ही और एक ही वस्तु के संदर्भ हैं। आप अपनी सुविधा के अनुसार दोनों तरह से प्रॉपर्टीज को जोड़ सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.