module.exports vs ekspor di Node.js

725

Saya telah menemukan kontrak berikut dalam modul Node.js:

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

Aku ingin tahu whats berbeda antara module.exportsdan exportsdan mengapa keduanya digunakan di sini.

Andreas Köberle
sumber
81
Sumber hebat: hacksparrow.com/node-js-exports-vs-module-exports.html ^ _ ^
Naftali alias Neal
6
Tautan 'untuk anak cucu' yang diperbarui
Zeke
8
Ini semua tentang referensi. Pikirkan ekspor seperti objek variabel lokal yang menunjuk ke module.exports. Jika Anda menimpa nilai ekspor, maka Anda kehilangan referensi ke module.exports, dan module.exports adalah apa yang Anda paparkan sebagai antarmuka publik.
Gabriel Llamas
14
Ringkasan Cepat: keduanya exportsdan module.exportsarahkan ke objek yang sama, kecuali jika Anda menetapkan kembali satu. Dan pada akhirnya module.exportsdikembalikan. Jadi jika Anda dipindahkan exportske suatu fungsi maka jangan berharap fungsi karena itu tidak akan dikembalikan. Namun jika Anda telah menetapkan fungsi seperti ini exports.func = function...maka hal yang dihasilkan akan memiliki properti func dengan fungsi sebagai nilai. Karena Anda menambahkan properti ke objek yang exportsmenunjuk ke ..
Muhammad Umer

Jawaban:

426

Pengaturan module.exportsmemungkinkan database_modulefungsi dipanggil seperti fungsi saat required. Pengaturan sederhana exportstidak akan memungkinkan fungsi untuk diekspor karena simpul mengekspor module.exportsreferensi objek . Kode berikut tidak akan mengizinkan pengguna untuk memanggil fungsi.

module.js

Berikut ini tidak akan berfungsi.

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

Berikut ini akan berfungsi jika module.exportsdiatur.

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

menghibur

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

Pada dasarnya node.js tidak mengekspor objek yang exportssaat ini referensi, tetapi mengekspor properti dari apa yang exportsawalnya referensi. Meskipun Node.js mengekspor module.exportsreferensi objek , memungkinkan Anda untuk memanggilnya seperti fungsi.


2 alasan paling tidak penting

Mereka mengatur keduanya module.exportsdan exportsmemastikan exportstidak merujuk objek yang diekspor sebelumnya. Dengan menetapkan kedua yang Anda gunakan exportssebagai steno dan menghindari bug potensial di kemudian hari.

Menggunakan exports.prop = true alih-alih module.exports.prop = truemenyimpan karakter dan menghindari kebingungan.

jeruk nipis
sumber
8
@ajostergaard: Kebetulan itu nama perpustakaan dari contoh OP diambil. Dalam modul, ini memungkinkan penulis untuk menulis hal-hal seperti nano.version = '3.3'bukan module.exports.version = '3.3', yang membaca sedikit lebih jelas. (Perhatikan bahwa nanoini adalah variabel lokal, dideklarasikan sedikit sebelum ekspor modul ditetapkan .)
josh3736
3
@ Lime - terima kasih - Saya senang itu sebagian besar tidak relevan karena jika bukan itu berarti saya akan salah mengerti semuanya. : - | :)
ostergaard
Hei Lime, ini adalah jawaban yang cukup lama tetapi saya harap Anda dapat mengklarifikasi sesuatu. Jika saya mengatur module.exportstetapi tidak exports , apakah kode saya masih berfungsi? Terima kasih atas bantuannya!
Asad Saeeduddin
1
@ Asad Ya, fungsi akan diekspor dengan benar asalkan Anda menyetelmodule.exports
Lime
@Liam terima kasih atas jawaban yang berharga. beberapa pertanyaan lagi - pada saat masuknya server.js, apa yang diharapkan dari nilai module.exports dan ekspor? apakah module.exports diharapkan menjadi nol dan ekspor disetel ke objek kosong? Apakah ini warisan atau ada beberapa use case yang valid untuk mengarahkan ekspor dan module.export ke dua objek yang berbeda?
Sushil
504

Meskipun pertanyaan telah dijawab dan diterima sejak lama, saya hanya ingin membagikan 2 sen saya:

Anda dapat membayangkan bahwa di awal file Anda ada sesuatu seperti (hanya untuk penjelasan):

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

masukkan deskripsi gambar di sini

Jadi, apa pun yang Anda lakukan, ingat saja itu module.exportsdan TIDAK exportsakan dikembalikan dari modul Anda saat Anda membutuhkan modul itu dari tempat lain.

Jadi ketika Anda melakukan sesuatu seperti:

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

Anda menambahkan 2 fungsi adan bke objek yang module.exportstitiknya juga, sehingga hasil typeofyang dikembalikan akan menjadi object:{ a: [Function], b: [Function] }

Tentu saja, ini adalah hasil yang sama yang akan Anda dapatkan jika Anda menggunakan module.exportsdalam contoh ini, bukan exports.

Ini adalah kasus di mana Anda ingin Anda module.exportsberperilaku seperti wadah nilai yang diekspor. Sedangkan, jika Anda hanya ingin mengekspor fungsi konstruktor maka ada sesuatu yang harus Anda ketahui tentang penggunaan module.exportsatau exports; (Ingat lagi yang module.exportsakan dikembalikan saat Anda membutuhkan sesuatu, bukan export).

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

Sekarang typeofhasil yang dikembalikan adalah 'function'dan Anda dapat meminta dan segera memohon seperti:
var x = require('./file1.js')();karena Anda menimpa hasil yang kembali menjadi suatu fungsi.

Namun, menggunakan exportsAnda tidak dapat menggunakan sesuatu seperti:

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

Karena dengan exports, referensi tidak menunjuk lagi ke objek di mana module.exportsmenunjuk, jadi tidak ada hubungan antara exportsdan module.exportslagi. Dalam hal ini module.exportsmasih menunjuk ke objek kosong {}yang akan dikembalikan.

Jawaban yang diterima dari topik lain juga akan membantu: Apakah Javascript lulus dengan referensi?

Srle
sumber
2
Penjelasan yang bagus tapi saya masih tidak mengerti bagaimana Anda dapat sepenuhnya menghilangkan module.exportsdari modul, misalnya dalam npmpaket ini : github.com/tj/consolidate.js/blob/master/lib/consolidate.js
CodyBugstein
4
@Gambar penjelasannya ada di sini: Apakah JavaScript lulus dengan referensi? exports.a = function(){}; works, exports = function(){} doesn't work
Cirpo
29
oooo akhirnya jawaban ini menjelaskannya. Pada dasarnya ekspor mengacu pada objek yang dapat Anda tambahkan properti tetapi jika Anda menetapkan kembali fungsinya maka Anda tidak lagi melampirkan properti ke objek asli itu. Sekarang ekspor merujuk ke fungsi sementara module.exports masih menunjuk ke objek itu dan karena itu yang dikembalikan. Anda dapat mengatakan bahwa ekspor pada dasarnya adalah pengumpulan sampah.
Muhammad Umer
5
Jadi, apa gunanya menggunakan exports? Mengapa tidak selalu digunakan module.exportsjika itu hanya penugasan kembali variabel? Sepertinya membingungkan saya.
jedd.ahyoung
1
@ jedd.ahyoung Menulis dan exports.somethingbukannya rumitmodule.exports.something
Srle
209

Pada dasarnya jawabannya terletak pada apa yang sebenarnya terjadi ketika sebuah modul diperlukan melalui requirepernyataan. Dengan asumsi ini adalah pertama kali modul diperlukan.

Sebagai contoh:

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

isi file1.js:

module.exports = '123';

Ketika pernyataan di atas dieksekusi, sebuah Moduleobjek dibuat. Fungsi konstruktornya adalah:

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

Seperti yang Anda lihat setiap objek modul memiliki properti dengan nama exports. Inilah yang akhirnya dikembalikan sebagai bagian dari require.

Langkah selanjutnya adalah membungkus isi file1.js menjadi fungsi anonim seperti di bawah ini:

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

Dan fungsi anonim ini dipanggil dengan cara berikut, di modulesini mengacu pada ModuleObyek yang dibuat sebelumnya.

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

Seperti yang dapat kita lihat di dalam fungsi, exportsargumen formal merujuk module.exports. Intinya itu adalah kenyamanan yang diberikan kepada programmer modul.

Namun kenyamanan ini perlu dilakukan dengan hati-hati. Dalam kasus apa pun jika mencoba untuk menetapkan objek baru untuk ekspor memastikan kami melakukannya dengan cara ini.

exports = module.exports = {};

Jika kita melakukannya dengan cara yang salah , module.exportsmasih akan menunjuk ke objek yang dibuat sebagai bagian dari instance modul.

exports = {};

Akibatnya menambahkan sesuatu ke objek ekspor di atas tidak akan berpengaruh pada objek module.exports dan tidak ada yang akan diekspor atau dikembalikan sebagai bagian dari persyaratan.

Chandu
sumber
8
Kehilangan saya di siniexports = module.exports = {};
Rusa Rusa
2
Saya pikir ini harus menjadi jawaban terbaik, itu menjelaskan mengapa func()gagal dalam jawaban @ William!
turtledove
2
Saya tidak melihat keuntungan untuk ditambahkan exports = module.exports = app;pada baris terakhir dari kode. Sepertinya module.exportsakan diekspor dan kami tidak akan pernah menggunakan exports, karena sekali lagi itu pada baris terakhir dari kode. Jadi, kenapa tidak kita tambahkan sajamodule.exports = app;
lvarayut
79

Awalnya,, module.exports=exportsdan requirefungsi mengembalikan objek yang module.exportsdimaksud.

jika kita menambahkan properti ke objek, katakanlah exports.a=1, maka module.exports dan ekspor masih merujuk ke objek yang sama. Jadi jika kita panggil mengharuskan dan menetapkan modul ke variabel, maka variabel tersebut memiliki properti a dan nilainya 1;

Tetapi jika kita menimpa salah satu dari mereka, misalnya, exports=function(){}maka mereka berbeda sekarang: ekspor merujuk ke objek dan modul baru. Ekspor merujuk ke objek asli. Dan jika kita memerlukan file, itu tidak akan mengembalikan objek baru, karena module.exports tidak merujuk ke objek baru.

Bagi saya, saya akan terus menambahkan properti baru, atau menimpa keduanya ke objek baru. Menimpa satu saja tidak benar. Dan perlu diingat bahwa itu module.exportsadalah bos yang sebenarnya.

kameron
sumber
1
Ya, ini sebenarnya jawaban sebenarnya. Ini singkat dan jelas. Orang lain mungkin benar tetapi penuh dengan istilah-istilah mewah dan tidak fokus tepat pada jawaban untuk pertanyaan ini.
Khoa
Sejauh ini, inilah jawaban yang paling jelas! Jika Anda ingin mem-bookmark-nya, ini adalah tautan yang tepat: stackoverflow.com/questions/7137397/…
lambdarookie
56

exportsdan module.exportssama kecuali Anda menetapkan kembali exportsdalam modul Anda.

Cara termudah untuk memikirkannya, adalah dengan berpikir bahwa baris ini secara implisit ada di bagian atas setiap modul.

var exports = module.exports = {};

Jika, dalam modul Anda, Anda menetapkan kembali exports, maka Anda menetapkan kembali dalam modul Anda dan tidak lagi sama module.exports. Inilah sebabnya, jika Anda ingin mengekspor suatu fungsi, Anda harus melakukan:

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

Jika Anda hanya menetapkan function() { ... }untuk exportsAnda, Anda akan ditugaskan exportsuntuk tidak lagi menunjuk ke module.exports.

Jika Anda tidak ingin merujuk ke fungsi Anda module.exportssetiap saat, Anda dapat melakukan:

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

Perhatikan bahwa module.exportsitulah argumen paling kiri.

Melampirkan properti ke exportstidak sama karena Anda tidak menugaskannya kembali. Itu sebabnya ini bekerja

exports.foo = function() { ... }
dustin.schultz
sumber
9
Ini adalah yang termudah untuk dipahami dari semua jawaban!
Adarsh ​​Konchady
2
Bagus dan lugas
fibono
1
Cara sederhana dan mudah untuk memahami fitur ini.
FilipeCanatto
27

JavaScript melewati objek dengan salinan referensi

Ini perbedaan yang halus untuk dilakukan dengan cara benda dilewatkan dengan referensi dalam JavaScript.

exportsdan module.exportskeduanya menunjuk ke objek yang sama. exportsadalah variabel dan module.exportsmerupakan atribut dari objek modul.

Katakanlah saya menulis sesuatu seperti ini:

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

exportsdan module.exportssekarang arahkan ke objek yang berbeda. Memodifikasi ekspor tidak lagi memodifikasi module.exports.

Ketika fungsi impor memeriksa module.exportsmendapat{b:12}

superluminary
sumber
6
Jawaban terbaik imho!
Tn. AJ
1
"JavaScript melewati referensi" - No.
xehpuk
13

Saya hanya membuat beberapa tes, ternyata, di dalam kode modul nodejs, seharusnya ada sesuatu seperti ini:

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

begitu:

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: tapi, dalam hal ini

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 Lai
sumber
Lyman, jadi module.exportsini semacam 'real-deal' yang simpulnya padam, tetapi pada titik tertentu Anda harus menambahkan semua exportske module.exportskecuali Anda menggunakan exports.namespace(kasus 2 di atas), yang dalam kasus itu tampaknya seperti Node menjalankan extends(module.exports, exports);menambahkan semua 'ruang nama' exportske module.exportsobjek? Dengan kata lain, jika Anda menggunakan exportsmaka Anda mungkin ingin menetapkan properti di atasnya?
Cody
11

Berikut ini adalah deskripsi yang baik yang ditulis tentang modul simpul di node.js dalam buku aksi dari publikasi Manning .
Apa yang akhirnya diekspor dalam aplikasi Anda adalah module.exports.
ekspor
diatur hanya sebagai referensi global ke module.exports , yang awalnya didefinisikan sebagai objek kosong yang dapat Anda tambahkan properti. Jadi exports.myFunc hanya singkatan untuk module.exports.myFunc .

Akibatnya, jika ekspor diatur ke hal lain, itu mematahkan referensi antara module.exports dan ekspor . Karena module.exportsadalah apa yang benar-benar diekspor, ekspor tidak lagi berfungsi seperti yang diharapkan — itu tidak merujuk modul .ekspor lagi. Jika Anda ingin mempertahankan tautan itu, Anda dapat membuat ekspor referensi module.exports lagi sebagai berikut:

module.exports = exports = db;
Salar
sumber
8

Saya telah melalui beberapa tes dan saya pikir ini dapat menjelaskan masalah ini ...

app.js:

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

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

Saya bahkan menambahkan file baru:

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

Kami mendapatkan output "@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(){};

Kami mendapatkan output "@routes {fn: {}, pengguna: {}}"


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

Kami mendapatkan output "@routes {user: [Fungsi: user]}" Jika kita mengubah user.jske { ThisLoadedLast: [Function: ThisLoadedLast] }, kita mendapatkan output "@routes {ThisLoadedLast: [Fungsi: ThisLoadedLast]}".


Tetapi jika kita memodifikasi ./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(){};

... kita mendapatkan "@routes {fn: {fn: [Function: fn]}, ThisLoadedLast: {ThisLoadedLast: [Function: ThisLoadedLast]}}"

Jadi saya sarankan selalu gunakan module.exportsdalam definisi modul Anda.

Saya tidak sepenuhnya mengerti apa yang terjadi secara internal dengan Node, tetapi tolong beri komentar jika Anda dapat lebih memahami hal ini karena saya yakin itu membantu.

- Selamat coding

Cody
sumber
Saya pikir mereka tidak perlu rumit dan membingungkan. Itu harus transparan dan intuitif.
ngungo
Saya setuju. Ini mungkin berguna untuk namespacing adalah beberapa keadaan, tetapi umumnya tidak akan membuat atau merusak apa pun.
Cody
4

Ini menunjukkan cara require()kerjanya dalam bentuknya yang paling sederhana, disarikan dari Eloquent JavaScript

Masalah Tidak mungkin bagi modul untuk secara langsung mengekspor nilai selain objek ekspor, seperti fungsi. Sebagai contoh, sebuah modul mungkin hanya ingin mengekspor konstruktor dari tipe objek yang didefinisikannya. Saat ini, ia tidak dapat melakukan itu karena mengharuskan selalu menggunakan exportsobjek yang dibuatnya sebagai nilai yang diekspor.

Solusi Menyediakan modul dengan variabel lain module,, yang merupakan objek yang memiliki properti exports. Properti ini pada awalnya menunjuk pada objek kosong yang dibuat dengan membutuhkan tetapi dapat ditimpa dengan nilai lain untuk mengekspor sesuatu yang lain.

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);
onmyway133
sumber
Saya harus membuat ulang ini di Node dan menguji beberapa hal sampai saya dapatkan, saya payah. Pada dasarnya, fungsi dalam yang dibuat untuk modul bahkan tidak pernah mengembalikan objek ekspor. Jadi objek "ekspor" sebenarnya tidak dipindahkan ke modul misalnya jika Anda mencoba menulis ekspor = "sekarang ini adalah string" secara langsung. Objek hanya ada sebagai referensi. Ini adalah perilaku yang saya pikir tidak benar-benar saya pahami sampai sekarang.
danielgormly
4

Ini adalah hasil dari

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

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

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

masukkan deskripsi gambar di sini

Juga:

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

//YES

Catatan: Spesifikasi CommonJS hanya memungkinkan penggunaan variabel ekspor untuk mengekspos anggota publik. Oleh karena itu, pola ekspor bernama adalah satu-satunya yang benar-benar kompatibel dengan spesifikasi CommonJS. Penggunaan module.exports adalah ekstensi yang disediakan oleh Node.js untuk mendukung serangkaian pola definisi modul yang lebih luas.

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

// Pertama, ekspor dan module.exports menunjuk Obyek kosong yang sama

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

exp.attr = "change";

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

// Jika Anda mengarahkan exp ke objek lain alih-alih mengarahkannya ke objek lain. Md.exp akan menjadi Objek kosong {}

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

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

console.log(md.exp); //{}
Anson Hwang
sumber
4

Dari dokumen

Variabel ekspor tersedia dalam ruang lingkup tingkat file modul, dan diberi nilai module.exports sebelum modul dievaluasi.

Itu memungkinkan jalan pintas, sehingga module.exports.f = ... dapat ditulis lebih ringkas sebagai exports.f = .... Namun, perlu diketahui bahwa seperti variabel apa pun, jika nilai baru ditetapkan untuk ekspor, itu adalah tidak lagi terikat ke module.exports:

Ini hanya variabel yang menunjuk ke module.exports.

ANewGuyInTown
sumber
4

Saya menemukan tautan ini berguna untuk menjawab pertanyaan di atas.

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

Untuk menambahkan ke posting lain Sistem modul dalam simpul tidak

var exports = module.exports 

sebelum menjalankan kode Anda. Jadi ketika Anda ingin mengekspor = foo, Anda mungkin ingin melakukan module.exports = ekspor = foo tetapi menggunakan exports.foo = foo harus baik-baik saja

Sudhir Srinivasan
sumber
git link rusak
Jesse Hattabaugh
Tautan sekarang diperbaiki.
Paweł Gościcki
3

"Jika Anda ingin root ekspor modul Anda menjadi fungsi (seperti konstruktor) atau jika Anda ingin mengekspor objek lengkap dalam satu tugas alih-alih membangunnya satu properti pada satu waktu, tetapkan ke module.exports daripada ekspor. " - http://nodejs.org/api/modules.html

madKakoo
sumber
3

module.exportsdan exportskeduanya menunjuk ke objek yang sama sebelum modul dievaluasi.

Setiap properti yang Anda tambahkan ke module.exports objek akan tersedia ketika modul Anda digunakan dalam modul lain menggunakan requirepernyataan. exportsadalah jalan pintas yang tersedia untuk hal yang sama. Contohnya:

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

setara dengan menulis:

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

Jadi tidak apa-apa asalkan Anda tidak menetapkan nilai baru ke exportsvariabel. Ketika Anda melakukan sesuatu seperti ini:

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

karena Anda menetapkan nilai baru untuk exportsitu tidak lagi memiliki referensi ke objek yang diekspor dan dengan demikian akan tetap lokal ke modul Anda.

Jika Anda berencana untuk menetapkan nilai baru module.exportsdaripada menambahkan properti baru ke objek awal yang tersedia, Anda mungkin harus mempertimbangkan melakukan seperti yang diberikan di bawah ini:

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

Situs web Node.js memiliki penjelasan yang sangat bagus tentang ini.

Justin Pathrose Vareed
sumber
2

1.ekspor -> gunakan sebagai utilitas tunggal
2. modul-ekspor -> gunakan sebagai objek logis seperti layanan, model dll

saingan
sumber
2

Mari kita buat satu modul dengan 2 cara:

Satu arah

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

module.exports = aa;

Cara kedua

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

Dan ini adalah bagaimana mengharuskan () akan mengintegrasikan modul.

Cara pertama:

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

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

    return module.exports;
}

Cara kedua

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

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

    return module.exports;
}
Dmitry Sergeev
sumber
2

mengapa keduanya digunakan di sini

Saya percaya mereka hanya ingin menjadi jelas bahwa module.exports,, exportsdan nanoarahkan ke fungsi yang sama - memungkinkan Anda untuk menggunakan salah satu variabel untuk memanggil fungsi dalam file. nanomenyediakan beberapa konteks untuk fungsi apa yang dilakukan.

exportstidak akan diekspor (hanya module.exportsakan), jadi mengapa repot-repot menimpanya juga?

Trade-off verbosity membatasi risiko bug di masa depan, seperti menggunakan exportsalih-alih module.exportsdalam file. Ini juga memberikan klarifikasi bahwa module.exportsdan exportspada kenyataannya menunjuk ke nilai yang sama.


module.exports vs. exports

Selama Anda tidak menetapkan ulang module.exportsatau exports(dan malah menambahkan nilai ke objek yang sama-sama mereka maksudkan), Anda tidak akan memiliki masalah apa pun dan dapat menggunakan dengan aman exportsuntuk lebih ringkas.

Saat menetapkan salah satu ke non-objek, mereka sekarang menunjuk ke berbagai tempat yang dapat membingungkan kecuali Anda sengaja ingin module.exportsmenjadi sesuatu yang spesifik (seperti fungsi).

Pengaturan exportske non-objek tidak masuk akal karena Anda harus mengatur module.exports = exportspada akhirnya untuk dapat menggunakannya dalam file lain.

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

Mengapa ditugaskan module.exportske suatu fungsi?

Lebih ringkas! Bandingkan seberapa pendek contoh kedua:

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

JBallin
sumber
2

masukkan deskripsi gambar di sini

Setiap file yang Anda buat adalah modul. modul adalah objek. Ini memiliki properti yang disebut exports : {}objek kosong secara default.

Anda dapat membuat fungsi / middlewares dan menambah ekspor kosong ini keberatan seperti exports.findById() => { ... } itu requiredi mana saja di aplikasi Anda dan penggunaan ...

controllers / user.js

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

mengharuskan dalam route.js untuk menggunakan:

const {findyId} = './controllers/user'
Ryan Dhungel
sumber
2

Untuk memahami perbedaannya, Anda harus terlebih dahulu memahami apa yang dilakukan Node.js untuk setiap modul selama runtime. Node.js membuat fungsi wrapper untuk setiap modul:

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

 })()

Perhatikan param pertama exportsadalah objek kosong, dan param ketiga moduleadalah objek dengan banyak properti, dan salah satu properti dinamai exports. Ini dari mana exportsdatangnya dan dari mana module.exportsdatangnya. Yang pertama adalah objek variabel, dan yang terakhir adalah properti dari moduleobjek.

Di dalam modul, Node.js secara otomatis melakukan hal ini di awal :,module.exports = exports dan akhirnya kembali module.exports.

Jadi Anda dapat melihat bahwa jika Anda menetapkan kembali beberapa nilai exports, itu tidak akan berpengaruh apa pun module.exports. (Hanya karena exportsmenunjuk ke objek baru lain, tetapi module.exportsmasih memegang yang lama exports)

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

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

Tetapi jika Anda memperbarui properti exports, itu pasti akan berpengaruh module.exports. Karena mereka berdua menunjuk ke objek yang sama.

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

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

Juga perhatikan bahwa jika Anda menetapkan kembali nilai lain module.exports, maka tampaknya tidak ada artinya untuk exportspembaruan. Setiap pembaruan aktif exportsdiabaikan karena module.exportsmenunjuk ke objek lain.

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

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

di node js module.js file digunakan untuk menjalankan module.load sistem.sekali kali node mengeksekusi file itu membungkus konten file js Anda sebagai berikut

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

karena ini membungkus di dalam kode sumber Anda dapat mengakses ekspor, memerlukan, modul, dll. pendekatan ini digunakan karena tidak ada cara lain untuk mendapatkan fungsionalitas menulis di file js ke yang lain.

lalu simpul jalankan fungsi terbungkus ini menggunakan c ++. pada saat itu ekspor objek yang masuk ke fungsi ini akan diisi.

Anda dapat melihat di dalam parameter fungsi ini ekspor dan modul. sebenarnya ekspor adalah anggota publik dari fungsi konstruktor modul.

lihat kode berikut

salin kode ini ke 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();

salin kode ini ke 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');}

sekarang jalankan menggunakan node

ini adalah output

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

ekspor adalah [Objek objek]

object.keys of foo: name is function () {console.log ('function to module ekspor')} berfungsi untuk ekspor modul

sekarang hapus baris yang dikomentari di a.js dan komentari baris di atas baris itu dan hapus baris terakhir dari b.js dan jalankan.

di dunia javascript Anda tidak dapat menetapkan kembali objek yang lulus sebagai parameter tetapi Anda dapat mengubah anggota publik fungsi ketika objek fungsi tersebut ditetapkan sebagai parameter ke fungsi lain

ingat

gunakan module.exports aktif dan hanya jika Anda ingin mendapatkan suatu fungsi saat Anda menggunakan membutuhkan kata kunci. dalam contoh di atas kita var foo = membutuhkan (a.js); Anda dapat melihat kami dapat memanggil foo sebagai fungsi;

ini adalah bagaimana dokumentasi simpul menjelaskannya "Objek ekspor dibuat oleh sistem Module. Kadang-kadang ini tidak dapat diterima, banyak yang ingin modul mereka menjadi turunan dari beberapa kelas. Untuk melakukan ini, tetapkan objek ekspor yang diinginkan ke module.exports."

sidias
sumber
0
  1. Keduanya module.exportsdan exportsmenunjuk ke hal yang sama 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"

    Anda dapat mengubah bpada baris 3 ke a, outputnya terbalik. Kesimpulannya adalah:

    adan bindependen.

  2. Jadi module.exports = exports = nano = function database_module(cfg) {...}sama dengan:

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

    Diasumsikan di atas adalah module.js, yang diperlukan oleh foo.js. Manfaat module.exports = exports = nano = function database_module(cfg) {...}jelas sekarang:

    • Dalam foo.js, karena module.exportsadalah require('./module.js'):

      var output = require('./modules.js')();
    • Di moduls.js: Anda dapat menggunakan exportssebagai gantinya module.exports.

Jadi, Anda akan senang jika keduanya exportsdan module.exportsmenunjuk ke hal yang sama.

Hujan
sumber