CommonJs Modül Sisteminde “module.exports” ve “export” arasındaki fark


277

Bu sayfada ( http://docs.nodejitsu.com/articles/getting-started/what-is-require ), "Dışa aktarma nesnesini bir işleve veya yeni bir nesneye ayarlamak istiyorsanız, module.exports nesnesini kullanın. "

Sorum neden?

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

Ben console.log sonucu ( result=require(example.js)) ve birincisi [Function]ikincisidir {}.

Bunun nedenini açıklar mısınız? Burada yazıyı okudum: Node.js'deki module.exports vs export . Yardımcı olur, ancak bu şekilde tasarlanma nedenini açıklamaz. İhracatın referansı doğrudan iade edilirse bir sorun olacak mı?


11
Her zaman kullanın module.exports.
Gabriel Llamas

1
Yukarıda belirtilen tavsiyelere uymak bu sorunun önlenmesine izin verdiğini düşünüyorum.
Vitalii Korsakov

@GabrielLlamas peki neden birçok paket kullanıyor exports, örneğin github.com/tj/consolidate.js/blob/master/lib/consolidate.js ?
CodyBugstein

3
@Imray her zaman kullanırsanız module.exports, yanlış asla ama kullanabilirsiniz exportssize basitçe böyle özelliklere eklerseniz, varsayılan ihraç nesneyi değiştirilmesi değilseniz: var foo = require('foo').foo. Bu fooözellik şu şekilde dışa aktarılabilir: exports.foo = ...ve tabii ki module.exports. Bu kişisel bir seçim ama şu anda module.exportsve exportsuygun şekilde kullanıyorum .
Gabriel Llamas

Export.myFunc = function () {} 'i tercih ediyorum, bu yüzden dosyanın altındaki ihracat listesini tutmak zorunda değilim. ES6'da beyan ettiğinizde, yaygın ihracat uygulamasına daha yakın hissediyor.
SacWebDeveloper

Yanıtlar:


625

moduleözelliği olan düz bir JavaScript nesnesidir exports. exportsolarak ayarlanan düz bir JavaScript değişkenidir module.exports. Dosyanızın sonunda node.js temelde olacak 'dönüş' module.exportsiçin requirefonksiyonu. Düğümdeki bir JS dosyasını görüntülemenin basitleştirilmiş bir yolu şu olabilir:

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

// your code

return module.exports;

Eğer bir özelliği ayarlamak exportsgibi exports.a = 9;ayarlayacaktır, module.exports.anesneler JavaScript referanslar, aynı nesneye birden değişkenleri kümesi, onlar anlama geldiğini olarak etrafında geçirilen çünkü hem vardır hepsi aynı nesne; o zaman exportsve module.exportsaynı nesnedir.
Belirlediğiniz Ama eğer exportsyeni bir şey için, artık ayarlanacaktır module.exportsbu yüzden, exportsve module.exportsartık aynı nesne bulunmaktadır.


11
Doğru, sadece referans türlerinin temelleri.
Vitalii Korsakov

18
Neden!? Bunu neden sadece burada okuyabilirsiniz. Bu, her modüler javaScript için kısa açıklama olmalıdır. Teşekkürler
lima_fil

8
Güzel açıkladı!
Aakash Verma

3
harika, en iyi cevap !!
John

5
Harika bir açıklama. Bununla ilgili belgeler de module.exportsbunu açıklamaktadır: nodejs.org/api/modules.html#modules_module_exports
Brian Morearty

52

Renee'nin cevabı iyi açıklanmıştır. Cevaba bir örnekle ekleme:

Düğüm dosyanızda çok şey yapar ve önemli olanlardan biri dosyanızı WRAPPING. Düğümün içindeki kaynak kodu "module.exports" döndürülür. Bir adım geri gidelim ve ambalajı anlayalım. Varsayalım

greet.js

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

module.exports = greet;

yukarıdaki kod, nodejs kaynak kodu içinde IIFE (Hemen Çağırılan İşlev İfadesi) olarak aşağıdaki gibi sarılır:

(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

ve yukarıdaki işlev çağrılır (.apply ()) ve döndürülen module.exports. Şu anda module. Aynı referansı gösteren ihracat ve ihracat yapmaktadır.

Şimdi, greet.js dosyasını tekrar yazdığınızı hayal edin.

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

çıktı olacak

[Function]
{}

nedeni: module.exports boş bir nesnedir. Module.exports için hiçbir şey ayarlamadık, yeni greet.js'de export = function () ..... ayarladık. Yani, module.exports boş.

Teknik olarak export ve module.exports aynı referansı işaret etmelidir (bu doğru !!). Ancak dışa aktarma işlevi () .... atarken, bellekte başka bir nesne oluşturan "=" kullanırız. Böylece, module.export ve export farklı sonuçlar üretir. İhracat söz konusu olduğunda, onu geçersiz kılamayız.

Şimdi, selamlama (Buna Mutation denir) selam.js (Renee cevabına atıfta bulunarak) olarak

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

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

çıktı olacak

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

Gördüğünüz gibi module.exports ve export bir işlev olan aynı referansı gösteriyor. Dışa aktarmalarda bir özellik ayarlarsanız, JS'de nesneler referansla geçtiğinden modül.exports'ta ayarlanır.

Sonuç her zaman karışıklığı önlemek için module.exports kullanmaktır. Bu yardımcı olur umarım. Mutlu kodlama :)


Bu da güzel ve anlaşılır bir cevaptır ve @ goto-bus-stop'un cevabını tamamlar. :)
varun

23

Ayrıca, anlamaya yardımcı olabilecek bir şey:

math.js

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

client.js

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

Harika, bu durumda:

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

Bu nedenle, varsayılan olarak, "this" aslında module.exports'a eşittir.

Ancak, uygulamanızı şu şekilde değiştirirseniz:

math.js

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

module.exports = {
    add: add
};

Bu durumda, iyi çalışır, ancak, "this" artık module.exports ile eşit değildir, çünkü yeni bir nesne yaratılmıştır.

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

Ve şimdi, gereksinim tarafından döndürülecek olan şey, modülün içinde tanımlanan şeydir. Artık bu değil veya ihracat değil.

Bunu yapmanın başka bir yolu:

math.js

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

Veya:

math.js

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

15

Arasındaki ilişki hakkında Rene cevabı exportsve module.exportsbu javascript başvurular hakkında, hepsi çok açık. Sadece şunu eklemek istiyorum:

Bunu birçok düğüm modülünde görüyoruz:

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

Bu, module.exports'u değiştirsek bile, bu iki değişkeni aynı nesneye işaret ederek dışa aktarmayı kullanabilmemizi sağlayacaktır.


Bu açıklama ile kafam karıştı, biraz ayrıntıya girmeli mi?
GuyFreakz

6
@GuyFreakz Emin bu karışıklığa konuşur eğer değilim ama module.exportsve exportsaynı nesneye başvuruda başlatıldı sadece ayrı değişkenler vardır. Bir değişkenin referans aldığı şeyi değiştirirseniz, iki değişken artık aynı şeye referans vermez. Yukarıdaki kod satırı, her iki değişkenin de aynı yeni nesneye başlatılmasını sağlar.
Andrew Palmer

Herkesin @fengshuo'da kaçırdığı gerçek bir kullanım durumu. Teşekkürler!
Aakash Verma

0

myTest.js

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

exports.put = function () {};

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

exportsve module.exportsaynı ve aynı nesneye müracaat bulunmaktadır. Size kolaylık sağlamak için özellikleri her iki şekilde de ekleyebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.