module.exports ve Node.js'de ihracat


725

Bir Node.js modülünde aşağıdaki sözleşmeyi buldum:

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

Ben neyin arasında farklı acaba module.exportsve exportsneden hem burada kullanılmaktadır.




6
'Gelecek için' bağlantısı güncellendi: nodejs.org/docs/latest/api/modules.html#modules_module_exports
Zeke

8
Her şey referanslarla ilgili. Dışa aktarmaları module.exports'u gösteren yerel değişken bir nesne gibi düşünün. Dışa aktarma değerinin üzerine yazarsanız, module.exports'a olan başvurunuzu kaybedersiniz ve module.exports, genel arabirim olarak gösterdiğiniz şeydir.
Gabriel Llamas

14
: Hızlı Özet hem exportsve module.exportsaynı nesneye gelin sürece yeniden atamakta biri. Ve sonunda module.exportsgeri döndü. exportsBir işleve yeniden atandığınızda , bir işlev döndürülmeyeceği için beklemeyin. Ancak böyle bir işlev atamış exports.func = function...olsaydınız, sonuç olarak func özelliği değer olarak işlev ile olurdu. Çünkü özelliği exportsişaret eden nesneye eklediniz ..
Muhammed Umer

Yanıtlar:


426

Ayar module.exports, database_modulefonksiyonun ne zaman fonksiyon gibi çağrılmasını sağlar required. exportsDüğüm nesne module.exportsbaşvurularını dışa aktardığından, ayar yalnızca işlevin dışa aktarılmasına izin vermez . Aşağıdaki kod kullanıcının işlevi çağırmasına izin vermez.

module.js

Aşağıdakiler işe yaramaz.

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

module.exportsAyarlanmışsa aşağıdakiler çalışır .

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

konsol

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

Temel olarak node.js , exportsşu anda başvuruda bulunan nesneyi dışa aktarmaz , ancak exportsbaşlangıçta başvuruda bulunanların özelliklerini dışa aktarır . Node.js nesne module.exportsreferanslarını dışa aktarmasına rağmen , onu bir işlev gibi çağırmanıza izin verir.


2. en az önemli neden

Her ikisi de set module.exportsve exportssağlamak için exportsönce ihraç nesneyi başvurmuyor. Her ikisini de kullanarakexports stenografi olarak ve ileride olası hatalardan kaçınırsınız.

Kullanma exports.prop = true yerine module.exports.prop = truekarakterler ve kaçınır karışıklığı kaydeder.


8
@ajostergaard: Sadece OP'nin örneğinin alındığı kütüphanenin adı oluyor . Modülde, yazarın nano.version = '3.3'yerine module.exports.version = '3.3'biraz daha net bir şekilde okunan gibi şeyler yazmasına izin verir . (Bunun nano, modül dışa
aktarımı

3
@ kireç - teşekkürler - büyük ölçüde alakasız olduğuna sevindim çünkü eğer olmasaydı her şeyi tamamen yanlış anlayacağım anlamına gelir. : - | :)
ostergaard

Hey Kireç, bu oldukça eski bir cevap ama umarım bir şeyi netleştirebilirsin. Ayarlayacak olsaydım module.exportsama yapmazsam exports , kodum hala çalışır mıydı? Herhangi bir yardım için teşekkürler!
Asad Saeeduddin

1
@Asad Evet ayarladığınız sürece işlev düzgün şekilde dışa aktarılacaktırmodule.exports
Lime

@Liam değerli cevap için teşekkürler. birkaç sorgu daha - server.js girişinde module.exports ve export değerlerinin ne olması bekleniyor? .exports öğesinin boş olması ve dışa aktarma işlemlerinin boş bir nesneye ayarlanması bekleniyor mu? Bu eski mi yoksa ihracat ve module.export'u iki farklı nesneye yönlendirmek için geçerli bir kullanım durumu var mı?
Sushil

504

Soru uzun zaman önce cevaplanıp kabul edilmiş olsa da, sadece 2 sentimi paylaşmak istiyorum:

Dosyanızın en başında şuna benzer bir şey olduğunu hayal edebilirsiniz (sadece açıklama için):

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

resim açıklamasını buraya girin

Böylece ne yaparsanız yapın, modülün başka bir yerden istenmesi durumunda modülünüzden module.exportsNOT exportsdöndürüleceğini unutmayın.

Yani şöyle bir şey yaptığınızda:

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

2 işlevi ave büzerinde de module.exportsişaret eden nesneye ekliyorsunuz , böylece typeofdönen sonuç bir olacaktır object:{ a: [Function], b: [Function] }

Tabii ki, bu, module.exportsbunun yerine bu örnekte kullanıyorsanız alacağınız aynı sonuçtur exports.

Bu, module.exportsdışa aktarılan değerlerin bir kabı gibi davranmanızı istediğiniz durumdur . Ancak, yalnızca bir yapıcı işlevini dışa aktarmak istiyorsanız, o zaman module.exportsveya hakkında bir şeyler bilmeniz gerekir exports; (Bir module.exportsşeye ihtiyaç duyduğunuzda döndürülmeyeceğini tekrar unutmayın export).

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

Şimdi typeofsonuç döndürülür 'function've bunu isteyebilir ve hemen aşağıdaki gibi çağırabilirsiniz:
var x = require('./file1.js')();çünkü dönen sonucun üzerine bir işlev olarak yazarsınız.

Ancak, kullanmak exportsgibi bir şey kullanamazsınız:

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

Çünkü ile exports, referans artık noktaların işaretlendiği nesneye işaret etmiyor module.exports, bu yüzden exportsve module.exportsartık bir ilişki yok. Bu durumda module.exportsyine {}de döndürülecek boş nesneyi gösterir .

Başka bir konunun kabul edilen cevabı da yardımcı olacaktır: Javascript referans ile geçiyor mu?


2
Güzel bir açıklama ama yine de module.exportsbir modülden nasıl tamamen çıkabileceğinizi anlamıyorum , örneğin bu npmpakette: github.com/tj/consolidate.js/blob/master/lib/consolidate.js
CodyBugstein

4
@ Açıklama burada: JavaScript referans ile geçiyor mu? exports.a = function(){}; works, exports = function(){} doesn't work
cirpo

29
Oooo sonunda bu cevap açıklıyor. Temelde dışa aktarma, özellikler ekleyebileceğiniz bir nesneyi ifade eder, ancak işlevine yeniden atadığınızda , o orijinal nesneye artık bir özellik eklemezsiniz . Module.exports hala bu nesneyi işaret ederken ve döndürülen şey olduğundan, dışa aktarma işlevine bakın. İhracatın temelde çöp toplandığını söyleyebilirsiniz.
Muhammed Umer

5
Öyleyse, kullanmanın anlamı exportsnedir? Neden sadece module.exportsdeğişken bir atama ise sadece her zaman kullanılmıyor ? Bana kafa karıştırıcı görünüyor.
jedd.ahyoung

1
@ jedd.ahyoung Bunun exports.somethingyerine yazmak daha az zahmetlimodule.exports.something
Srle

209

Temel olarak cevap, bir modül requiredeyim yoluyla gerektiğinde gerçekte ne olduğudur . Modülün ilk kez gerektiği varsayılırsa.

Örneğin:

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

file1.js içeriği:

module.exports = '123';

Yukarıdaki ifade yürütüldüğünde, bir Modulenesne oluşturulur. Yapıcı işlevi:

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

Gördüğünüz gibi her modül nesnesinin adında bir özelliği vardır exports. Sonunda bir parçası olarak iade edilen budur require.

Bir sonraki gereksinim dosyası, file1.js dosyasının içeriğini aşağıdaki gibi anonim bir işleve sarmaktır:

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

Ve bu anonim işlev aşağıdaki şekilde çağrılır, moduleburada Moduledaha önce oluşturulan Nesne anlamına gelir .

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

Fonksiyonun içinde görebildiğimiz gibi, exportsresmi argümandan bahseder module.exports. Aslında, modül programcısına sağlanan kolaylık.

Bununla birlikte, bu kolaylığın dikkatle kullanılması gerekir. Her durumda, dışa aktarma işlemlerine yeni bir nesne atamaya çalışıyorsanız, bunu bu şekilde yaptığımızdan emin olun.

exports = module.exports = {};

Biz bu yol takip yaparsanız yanlış bir şekilde , module.exportshala modül örneğinin parçası olarak oluşturulan nesneyi işaret ediyor edilecektir.

exports = {};

Sonuç olarak, yukarıdaki dışa aktarma nesnesine herhangi bir şey eklemenin module.exports nesnesine hiçbir etkisi olmayacak ve hiçbir şey gereksinimin bir parçası olarak dışa aktarılacak veya döndürülmeyecektir.


8
Beni burada kaybettimexports = module.exports = {};
Dev Elk

2
Bunun en iyi cevap olması gerektiğini düşünüyorum, neden func()William'ın cevabında başarısız olduğunu açıklıyor !
turtledove

2
exports = module.exports = app;Kodun son satırına eklemek için herhangi bir avantaj görmüyorum . Görünüşe göre module.exportsirade ihraç edilecek ve asla kullanmayacağız exports, çünkü yine kodun son satırında. Peki, neden sadece basitçe module.exports = app;
eklemiyoruz

80

Başlangıçta, module.exports=exportsve requireişlevi nesnenin module.exportsbaşvurduğu döndürür .

Biz eğer özellik eklemek nesneye, diyelim ki exports.a=1, daha sonra module.exports ve ihracat hala aynı nesneye bakın. Bu nedenle, modülü bir değişkene atar ve atarsak, değişken a özelliğine sahiptir ve değeri 1 olur;

Biz Ama eğer geçersiz bunlardan biri, örneğin, exports=function(){}daha sonra bunlar farklı şimdi: ihracat Yeni bir nesneye atıfta ve module.exports orijinal nesneye bakın. Dosyaya ihtiyacımız olursa, module.exports yeni nesneye başvurmadığı için yeni nesneyi döndürmez.

Benim için, yeni özellik eklemeye devam edeceğim veya her ikisini de yeni bir nesneye geçersiz kılacağım. Sadece birini geçersiz kılmak doğru değil. Ve module.exportsbunun gerçek patron olduğunu unutmayın .


1
Evet, bu gerçek cevap. Kısa ve net. Diğerleri doğru ama süslü terimlerle dolu olabilir ve bu sorunun cevabına tam olarak odaklanmayabilir.
Khoa

Bu en açık cevap! Yer işareti eklemek istiyorsanız, bu kesin bağlantıdır: stackoverflow.com/questions/7137397/…
lambdarookie

57

exportsve modülünüzde module.exportsyeniden atamadığınız sürece aynıdır exports.

Bunu düşünmenin en kolay yolu, bu çizginin her modülün üstü örtülü olduğunu düşünmektir.

var exports = module.exports = {};

Modülünüz içinde yeniden exportsatarsanız, modülü modülünüzde yeniden atarsınız ve artık eşit olmaz module.exports. Bu nedenle, bir işlevi dışa aktarmak istiyorsanız şunları yapmanız gerekir:

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

Basitçe atanmış ise function() { ... }To exports, sen yeniden atama olacağını exportsartık noktaya module.exports.

İşlevinize module.exportsher zaman başvurmak istemiyorsanız şunları yapabilirsiniz:

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

module.exportsEn soldaki argüman olduğuna dikkat edin .

Yeniden atamadığınız için özellikleri eklemek exportsaynı değildir. Bu yüzden bu işe yarıyor

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

9
Bu, tüm cevapları anlamak için en kolay olanıydı!
Adarsh ​​Konchady

2
Güzel ve anlaşılır
fibono

1
Bu özelliği anlamanın basit ve kolay yolu.
FilipeCanatto

27

JavaScript, nesneleri bir referansın kopyasına göre geçirir

Nesnelerin JavaScript'te referans olarak geçirilme şekliyle ilgili küçük bir farktır.

exportsve module.exportsikisi de aynı nesneyi gösteriyor. exportsbir değişkendir ve module.exportsmodül nesnesinin bir özelliğidir.

Diyelim ki böyle bir şey yazıyorum:

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

exportsve module.exportsşimdi farklı nesnelere işaret edin. Dışa aktarmaları değiştirmek, module.exports'u artık değiştirmez.

İçe aktarma işlevi incelendiğinde module.exports,{b:12}


6
En iyi cevap imho!
Bay AJ

1
"JavaScript referans ile geçer" - Hayır.
xehpuk

13

Sadece bazı testler yapıyorum, nodejs modül kodunun içinde böyle bir şey olması gerektiği ortaya çıktı:

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

yani:

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: ancak, bu durumda

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)

Lyman, bu yüzden module.exportso düğüm kapalı gider fakat bir noktada tüm eklemeniz gerekir sıralama 'gerçek anlaşma' taşımaktadır senin exportsiçin module.exportsbir kullanmadığınız sürece exports.namespacebu durumda da olduğu gibi (davayı 2 üzeri), Düğüm bir ran extends(module.exports, exports);hepsi 'ad alanlarını' eklenmesi exportsiçin module.exportsnesnenin? Başka bir deyişle, kullanıyorsanız exportsmuhtemelen özellikleri ayarlamak mı istiyorsunuz?
Cody

11

İşte Manning yayınından eylem kitabında node.js'deki düğüm modülleri hakkında yazılmış iyi bir açıklama . Nihayetinde uygulamanıza ihraç edilen modül module.exports. ihracat için küresel referans olarak basitçe kurulur module.exports başlangıçta özellikler ekleyebilirsiniz yani boş nesne olarak tanımlanır. Yani exports.myFunc için sadece kısaltmasıdır module.exports.myFunc . Sonuç olarak, dışa aktarmalar başka bir şeye ayarlanırsa, module.exports ve dışa aktarmalar arasındaki referansı keser . Çünkü



module.exportsgerçekten ihraç edilen şey, ihracat artık beklendiği gibi çalışmayacak - artık modül .exports'a referans vermiyor . Bu bağlantıyı korumak istiyorsanız, module.exports referans dışa aktarmalarını aşağıdaki gibi tekrar yapabilirsiniz :

module.exports = exports = db;

8

Bazı testlerden geçtim ve bence bu konuya ışık tutabilir ...

app.js:

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

sürümleri /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] }"

Yeni dosyalar bile ekledim:

./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 {}" çıktısını alıyoruz


./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: {}, kullanıcı: {}}" çıktısını alıyoruz


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

Biz çıkış olsun "@routes {kullanıcıyı: [Fonksiyon: kullanıcı]}" Biz değiştirirseniz user.jsiçin { ThisLoadedLast: [Function: ThisLoadedLast] }, biz çıktı olsun "@routes {ThisLoadedLast: [Fonksiyon: ThisLoadedLast]}".


Ama değiştirirsek ./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(){};

... "@routes {fn: {fn: [İşlev: fn]}, ThisLoadedLast: {ThisLoadedLast: [İşlev: ThisLoadedLast]}}"

Bu yüzden her zaman kullanmanızı öneririm module.exports modül tanımlarınızda .

Node ile dahili olarak neler olup bittiğini tam olarak anlamıyorum, ancak bunun daha mantıklı olduğunu düşünüyorsanız lütfen yorum yapın.

- Mutlu kodlama


Sanırım gereksiz yere karmaşık ve kafa karıştırıcılar. Şeffaf ve sezgisel olmalıdır.
ngungo

Katılıyorum. Adlandırma için bazı durumlarda yararlı olabilir, ancak genellikle hiçbir şey yapmaz veya bozmaz.
Cody

4

Bu, Eloquent JavaScript'tenrequire() alıntılanarak en basit haliyle nasıl çalıştığını gösterir

Sorun Modülün dışa aktarma nesnesi dışında bir işlev gibi bir değeri doğrudan dışa aktarması mümkün değildir. Örneğin, bir modül yalnızca tanımladığı nesne türünün yapıcısını dışa aktarmak isteyebilir. Şimdilik bunu yapamaz, çünkü requir her zaman exportsoluşturduğu nesneyi dışa aktarılan değer olarak kullanır .

Çözüm Modüllere module, özelliği olan bir nesne olan başka bir değişken sağlayın exports. Bu özellik başlangıçta gereksinim tarafından oluşturulan boş nesneye işaret eder, ancak başka bir şey vermek için başka bir değerle üzerine yazılabilir.

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

Bunu Düğümde yeniden oluşturmak ve birkaç şey test edene kadar test ettim, berbattım. Temel olarak, modül için oluşturulan iç işlev dışa aktarma nesnesini bile döndürmez. Dolayısıyla, "export" nesnesi aslında modülde yeniden atanmaz, örneğin export = "doğrudan bu bir dizedir" yazmaya çalışırsanız. Nesne yalnızca başvuru olarak bulunur. Bu, şimdiye kadar gerçekten doğru bir şekilde aldığımı sanmıyorum.
danielgormly

4

İşte sonucu

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

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

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

resim açıklamasını buraya girin

Ayrıca:

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

//YES

Not: CommonJS spesifikasyonu yalnızca dışa aktarma değişkeninin herkese açık üyeleri ortaya çıkarmak için kullanılmasına izin verir. Bu nedenle, adlandırılan dışa aktarma modeli, CommonJS spesifikasyonu ile gerçekten uyumlu olan tek modeldir. Module.exports kullanımı, Node.js tarafından daha geniş bir dizi modül tanım şablonunu desteklemek için sağlanan bir uzantıdır.


4
var a = {},md={};

// İlk olarak, export ve module.exports aynı boş Nesneyi gösterir

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

exp.attr = "change";

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

// exp yerine başka bir nesneye işaret ederseniz, özelliği başka bir nesneye aittir. Md.exp nesnesi boş olacaktır {}

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

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

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

4

Gönderen docs

Dışa aktarma değişkeni bir modülün dosya düzeyinde kapsamı içinde bulunur ve modül değerlendirilmeden önce module.exports değerine atanır.

Bir kısayola izin verir, böylece module.exports.f = ... export olarak daha özlü bir şekilde yazılabilir. F = .... Ancak, herhangi bir değişken gibi, ihracata yeni bir değer atandıysa, Artık module.exports'a bağlı değil:

Sadece module.exports'u gösteren bir değişkendir.


4

Bu bağlantıyı yukarıdaki soruyu cevaplamak için yararlı buldum.

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

Diğer gönderilere eklemek için Düğümdeki modül sistemi

var exports = module.exports 

kodunuzu çalıştırmadan önce. Dışa aktarma = foo yapmak istediğinizde, muhtemelen module.exports = export = foo yapmak istersiniz, ancak export.foo = foo kullanmak iyi olur


git bağlantısı bozuk
Jesse Hattabaugh

Bağlantı düzeltildi.
Paweł Gościcki

3

"Modülünüzün dışa aktarımının kökünün bir işlev olmasını istiyorsanız (bir kurucu gibi) veya tam bir nesneyi tek seferde tek bir özellik oluşturmak yerine dışa aktarmak istiyorsanız, bunu modül yerine exex.exports'a atayın. ihracat." - http://nodejs.org/api/modules.html


3

module.exportsve exportsher ikisi de modül değerlendirilmeden önce aynı nesneyi gösterir.

module.exports Modüle başka bir modülde requiredeyim kullanılarak kullanıldığında , nesneye eklediğiniz tüm özellikler kullanılabilir . exportsaynı şey için kullanılabilen bir kısayoldur. Örneğin:

module.exports.add = (a, b) => a+b

yazmaya eşittir:

exports.add = (a, b) => a+b

exportsDeğişkene yeni bir değer atamadığınız sürece sorun olmaz . Böyle bir şey yaptığınızda:

exports = (a, b) => a+b 

yeni bir değer atadığınız için exports, artık dışa aktarılan nesneye referans yoktur ve bu nedenle modülünüz için yerel olarak kalır.

Kullanıma module.exportssunulan ilk nesneye yeni özellikler eklemek yerine yeni bir değer atamayı planlıyorsanız , muhtemelen aşağıda verildiği şekilde yapmayı düşünmelisiniz:

module.exports = exports = (a, b) => a+b

Node.js web sitesi bunun çok iyi bir açıklamasına sahiptir.


2

1.exports -> singleton yardımcı programı olarak kullanın
2. module- export -> hizmet, model vb. Gibi mantıksal nesneler olarak kullanın


2

2 yolla bir modül oluşturalım:

Tek yön

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

module.exports = aa;

İkinci yol

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

Bu, requir (()) modülünü nasıl entegre edecek.

İlk yol:

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

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

    return module.exports;
}

İkinci yol

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

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

    return module.exports;
}

2

neden ikisi de burada kullanılıyor

Ben sadece açık olmak istiyorum inanıyoruz module.exports, exportsve nanoaynı işleve noktası - Dosyanın içinden işlevini çağırmak için her iki değişkeni kullanmasına izin. nanoişlevin ne yaptığına dair bir bağlam sağlar.

exportsihraç edilmeyecek (sadece module.exportsolacak), o zaman neden bunun üzerine yazmaktan rahatsız oluyorsunuz?

Ayrıntı ticaret-off kullanmak gibi gelecek böcek riskini sınırlar exportsyerine module.exportsdosya içinde. Ayrıca sağlayan açıklık olduğunu module.exportsve exportsaynı değere işaret aslında.


module.exports vs exports

Yeniden atamadığınız module.exportsveya exports(ve her ikisinin de bahsettiği nesneye değerler eklemediğiniz) sürece, herhangi bir sorununuz olmaz ve exportsdaha özlü olmak için güvenle kullanabilirsiniz .

Herhangi bir nesneye olmayan bir nesne atarken, kasıtlı module.exportsolarak belirli bir şey (işlev gibi) olmak istemediğiniz sürece kafa karıştırıcı olabilecek farklı yerlere işaret ediyorlar .

Ayar exportsolmayan bir nesneye sete gerekecek kadar mantıklı değil module.exports = exportsdiğer dosyalarda kullanmak edebilmek için sonunda.

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

exports.msg = 'hi';
console.log(module.exports === exports); // true

exports = 'yo';
console.log(module.exports === exports); // false

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

module.exports = 'hello';
console.log(module.exports === exports); // false

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

Neden module.exportsbir fonksiyona atamalı ?

Daha kısa! 2. örneğin ne kadar kısa olduğunu karşılaştırın:

helloWorld1.js: module.exports.hello = () => console.log('hello world');

app1.js: let sayHello = require('./helloWorld1'); sayHello.hello; // hello world

helloWorld2.js: module.exports = () => console.log('hello world');

app2.js: let sayHello = require('./helloWorld2'); sayHello; // hello world


2

resim açıklamasını buraya girin

Oluşturduğunuz her dosya bir modüldür. modül bir nesnedir. exports : {}Varsayılan olarak boş nesne olarak adlandırılan özelliğe sahiptir .

Aşağıdaki gibi nesne işlevleri / ara katman oluşturmak ve bu boş ihracatına ekleyebilir exports.findById() => { ... } sonra requireuygulamanızdan ve kullanımda her yerde ...

kontrolörleri / user.js

exports.findById = () => {
    //  do something
}

kullanmak için route.js'de gerekli :

const {findyId} = './controllers/user'

2

Farklılıkları anlamak için önce Node.js'nin çalışma zamanı sırasında her modüle ne yaptığını anlamalısınız. Node.js her modül için bir sarma işlevi oluşturur:

 (function(exports, require, module, __filename, __dirname) {

 })()

İlk parametrenin exportsboş bir nesne olduğuna ve üçüncü parametrenin modulebirçok özelliğe sahip bir nesne olduğuna ve özelliklerden birinin adlandırıldığına dikkat edin exports. Bu ne olduğu exportsgelir ve ne module.exportsgeliyor. Birincisi değişken bir nesnedir ve ikincisi modulenesnenin bir özelliğidir .

Modül içinde, Node.js bu şeyi başlangıçta otomatik olarak yapar: module.exports = exportsve sonuç olarak geri döner module.exports.

Böylece exports, bir değeri yeniden atarsanız , bunun bir etkisi olmayacağını görebilirsiniz.module.exports . (Çünkü exportsbaşka bir yeni nesneyi işaret eder, ancak module.exportseskiyi tutar exports)

let exports = {};
const module = {};
module.exports = exports;

exports = { a: 1 }
console.log(module.exports) // {}

Ancak, exports , kesinlikle üzerinde etkisi olacaktır module.exports. Çünkü ikisi de aynı nesneyi gösteriyor.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports.b = 2;
console.log(module.exports) // { a: 1, b: 2 }

Ayrıca, başka bir değeri yeniden atarsanız module.exports, exportsgüncellemeler için anlamsız göründüğüne dikkat edin . Başka bir nesneyi işaret ettiği için her güncelleştirme exportsyok sayılır module.exports.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports = {
  hello: () => console.log('hello')
}
console.log(module.exports) // { hello: () => console.log('hello')}

0

Düğümde js module.js dosyası, düğümün bir dosyayı yürüttüğünde module.load system.every zamanını çalıştırmak için kullanılır.

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

çünkü ur js kaynak kodu içinde bu sarma ihracat, ihtiyaç, modül, vb erişebilirsiniz .. js dosya üzerine yazılan işlevsellikleri almak için başka bir yolu olmadığı için bu yaklaşım kullanılır.

daha sonra düğüm bu sarılmış işlevi c ++ kullanarak yürütür. o anda bu işleve aktarılan dışa aktarma nesnesi doldurulacaktır.

bu fonksiyonun içinde ihracat ve modül parametrelerini görebilirsiniz. aslında ihracat modül yapıcı fonksiyonunun halka açık bir üyesidir.

aşağıdaki koda bak

bu kodu b.js'ye kopyala

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

bu kodu a.js'ye kopyala

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

şimdi düğümü kullanarak çalıştır

bu çıktı

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

dışa aktarma [nesne Nesne]

foo: name is function () {console.log ('modül dışa aktarma işlevi')} modül dışa aktarma işlevi

şimdi a.js'de yorum yapılan satırı kaldırın ve bu satırın üstündeki satırı yorumlayın ve b.js'nin son satırını kaldırın ve çalıştırın.

javascript dünyasında parametre olarak geçen nesneyi yeniden atayamazsınız, ancak o işlevin nesnesi başka bir işleve parametre olarak ayarlandığında işlevin genel üyesini değiştirebilirsiniz

hatırla

module.exports özelliğini kullanın ve yalnızca anahtar kelime gerektiren bir işlevi kullanmak istediğinizde kullanın. yukarıdaki örnekte var foo = requir (a.js); foo'yu bir işlev olarak çağırabileceğimizi görebilirsiniz;

düğüm belgeleri bu şekilde bunu açıklar "Export nesnesi Modül sistemi tarafından oluşturulur. Bazen bu kabul edilemez, birçoğu modüllerinin bir sınıf örneği olmasını ister. Bunu yapmak için module.exports'a istenen verme nesnesini atayın."


0
  1. Hem module.exportsve exportsaynı gelin 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"

    bSatır 3 olarak değiştirebilirsiniz a, çıkış tersidir. Sonuç:

    ave bbağımsızdır.

  2. Yani module.exports = exports = nano = function database_module(cfg) {...}şuna eşittir:

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

    Yukarıda olduğu varsayılır module.js, bu gereklidir foo.js. 'Nin faydaları module.exports = exports = nano = function database_module(cfg) {...}şimdi açık:

    • In foo.jsberi module.exportsolduğu require('./module.js'):

      var output = require('./modules.js')();
    • İçinde moduls.js: exportsyerine kullanabilirsiniz module.exports.

Yani, her iki eğer mutlu olacak exportsve module.exportsaynı şey işaret.

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.