Modul
Node.js memperlakukan setiap fail JavaScript sebagai modul yang berasingan.Sebagai contoh, jika anda mempunyai fail yang mengandungi beberapa kod dan nama xyz.js
file ini, file ini akan dianggap sebagai modul di Node, dan anda boleh mengatakan bahawa anda telah membuat modul bernama xyz
.

Mari kita ambil contoh untuk memahami perkara ini dengan lebih baik.
Anda mempunyai fail bernama circle.js
yang terdiri dari logik untuk menghitung luas & keliling bulatan jejari tertentu, seperti yang diberikan di bawah:
bulatan.js
Anda boleh memanggil circle.js
fail modul bernama circle
.
Anda mungkin tertanya-tanya mengapa perlu mempunyai banyak modul? Anda mungkin hanya menulis semua kod dalam satu modul. Baiklah, sangat penting untuk menulis kod modular. Secara modular, saya bermaksud mengatakan bahawa kod anda harus bebas dan harus digabungkan secara longgar. Bayangkan bahawa terdapat aplikasi yang besar dan anda mempunyai semua kod anda ditulis di satu tempat, hanya satu fail. Terlalu tidak kemas, bukan?
Bagaimana kod yang ditulis di dalam modul dijalankan?
Sebelum menjalankan kod yang ditulis di dalam modul, Node mengambil keseluruhan kod dan memasukkannya ke dalam pembungkus fungsi. Sintaks pembungkus fungsi ini adalah:

Pembungkus fungsi untuk circle
modul akan kelihatan seperti yang diberikan di bawah:
Anda dapat melihat bahawa ada pembungkus fungsi di peringkat root yang merangkumi semua kod yang ditulis di dalam circle
modul.
Ini adalah kelebihan yang paling ketara kerana memiliki modul di Node.js. Walaupun anda menentukan pemboleh ubah global dalam modul menggunakan var
, let
atau const
kata kunci, pemboleh ubah tersebut dilingkari secara tempatan ke modul daripada dilingkupi secara global. Ini berlaku kerana setiap modul mempunyai fungsi pembungkus sendiri dan kod yang ditulis di dalam satu fungsi sesuai dengan fungsi tersebut dan tidak dapat diakses di luar fungsi ini.

Bayangkan bahawa terdapat dua modul - A dan B . Kod tertulis di dalam modul A dikurung dalam fungsi wrapper sepadan dengan modul . Perkara yang sama berlaku dengan hurufiah di dalam modul B . Oleh kerana kod yang berkaitan dengan kedua-dua modul tersebut dilampirkan dalam fungsi yang berlainan, fungsi-fungsi ini tidak akan dapat mengakses kod satu sama lain. (Ingat setiap fungsi dalam JavaScript mempunyai ruang lingkup tempatannya sendiri?) Inilah sebab mengapa modul A tidak dapat mengakses kod yang tertulis di dalam modul B dan sebaliknya.
Lima parameter - exports
, require
, module
, __filename
, __dirname
yang ada di dalam setiap modul dalam Nod. Walaupun parameter ini bersifat global untuk kod dalam modul namun sesuai dengan modul (kerana fungsi pembungkus seperti yang dijelaskan di atas). Parameter ini memberikan maklumat berharga yang berkaitan dengan modul.
Mari kita kaji semula circle
modul, yang anda lihat sebelumnya. Terdapat tiga konstruk yang ditentukan dalam modul ini - pemboleh ubah tetap PI
, fungsi dinamakan calculateArea
dan fungsi lain dinamakan calculateCircumference
. Perkara penting yang perlu diingat adalah bahawa semua konstruk ini adalah peribadi untuk circle
modul secara lalai. Ini bermaksud bahawa anda tidak boleh menggunakan konstruk ini dalam modul lain kecuali dinyatakan secara eksplisit.
Oleh itu, persoalan yang timbul sekarang ialah bagaimana anda menentukan sesuatu dalam modul yang boleh digunakan oleh beberapa modul lain? Ini adalah ketika module
& require
parameter fungsi pembungkus berfungsi. Mari kita bincangkan dua parameter ini dalam artikel ini.
module
The module
parameter (bukan kata kunci dalam modul di Node) merujuk kepada objek yang mewakili modul semasa . exports
adalah kunci module
objek, yang nilai yang sesuai adalah objek. Nilai lalai module.exports
objek adalah {}
(objek kosong). Anda boleh menyemaknya dengan mencatat nilai module
kata kunci di dalam mana-mana modul. Mari kita periksa berapa nilai module
parameter di dalam circle
modul.
bulatan.js
Perhatikan bahawa terdapat console.log(module);
pernyataan di akhir kod dalam fail yang diberikan di atas. Apabila anda melihat output, ia akan mencatat module
objek, yang mempunyai kunci bernama exports
dan nilai yang sesuai dengan kunci ini adalah {}
(objek kosong).
Sekarang, apa yang module.exports
dilakukan objek itu? Ia digunakan untuk menentukan perkara yang boleh dieksport oleh modul. Apa sahaja yang dieksport dari modul boleh, pada gilirannya, tersedia untuk modul lain. Mengeksport sesuatu agak mudah. Anda hanya perlu menambahkannya ke module.exports
objek. Terdapat tiga cara untuk menambahkan sesuatu ke module.exports
objek yang akan dieksport. Mari kita bincangkan kaedah ini satu persatu.
Kaedah 1:
(Mendefinisikan konstruk dan kemudian menggunakan beberapa module.exports
pernyataan untuk menambahkan sifat)
Dalam kaedah pertama, anda menentukan konstruk terlebih dahulu dan kemudian menggunakan beberapa modul. Mengeksport penyataan di mana setiap pernyataan digunakan untuk mengeksport sesuatu dari modul. Mari lihat kaedah ini dalam tindakan dan lihat bagaimana anda dapat mengeksport dua fungsi yang ditentukan dalam circle
modul.
bulatan.js
Seperti yang saya katakan sebelumnya, module
adalah objek yang mempunyai kunci bernama exports
dan kunci ini ( module.exports
), pada gilirannya, terdiri daripada objek lain. Sekarang, jika anda melihat kod yang diberikan di atas, semua yang anda lakukan adalah menambahkan sifat baru (pasangan nilai-kunci) ke module.exports
objek.
Harta pertama mempunyai kunci calculateArea
(ditakrifkan pada baris 19)dan nilai yang ditulis di sebelah kanan pengendali tugasan adalah fungsi yang ditentukan dengan nama calculateArea
(pada baris 9).
Harta kedua (ditakrifkan pada baris 20) mempunyai kunci calculateCircumference
dan nilai adalah fungsi yang ditentukan dengan nama calculateCircumference
(pada baris 16).
Oleh itu, anda telah menetapkan dua sifat (pasangan nilai-kunci) ke module.exports
objek.
Jangan lupa bahawa anda telah menggunakan notasi titik di sini. Anda boleh menggunakan notasi tanda kurung untuk menetapkan sifat ke module.exports
objek dan menambahkan fungsinya - calculateArea
dan calculateCircumference
dengan menentukan kunci berikut notasi tanda kurung. Oleh itu, anda boleh menulis dua baris berikut untuk menambahkan sifat ke module.exports
objek menggunakan notasi kurungan sambil mengganti dua baris terakhir (menggunakan notasi titik) dalam kod yang diberikan di atas:
// exporting stuff by adding to module.exports object using the bracket notation
module.exports['calculateArea'] = calculateArea;module.exports['calculateCircumference'] = calculateCircumference;
Mari sekarang cuba mencatat nilai module.exports
objek setelah menambahkan sifat. Perhatikan bahawa pernyataan berikut ditambahkan pada akhir kod dalam fail yang diberikan di bawah:
// logging the contents of module.exports object after adding properties to it
console.log(module.exports);
bulatan.js
Mari periksa output kod ini dan lihat apakah semuanya berjalan lancar. Untuk melakukan ini, simpan kod anda dan jalankan arahan berikut di Terminal anda :
node circle
Pengeluaran:
{ calculateArea: [Function: calculateArea], calculateCircumference: [Function: calculateCircumference] }
Konstruk - calculateArea
dan calculateCircumference
, ditambahkan ke module.exports
, objek dicatat. Oleh itu, anda berjaya menambahkan dua sifat dalam module.exports
objek sehingga fungsi - calculateArea
dan calculateCircumference
dapat dieksport dari circle
modul ke modul lain.
Dalam kaedah ini, anda pertama kali menentukan semua konstruk dan kemudian menggunakan beberapa modul. Mengeksport penyataan di mana setiap pernyataan digunakan untuk menambahkan harta benda ke module.exports
objek.
Kaedah 2:
(Mendefinisikan konstruk dan kemudian menggunakan satu module.exports
penyataan untuk menambahkan sifat)
Cara lain ialah menentukan semua konstruk terlebih dahulu (seperti yang anda lakukan dalam kaedah sebelumnya) tetapi gunakan satu module.exports
penyataan untuk mengeksport semuanya. Kaedah ini serupa dengan sintaks notasi literal objek di mana anda menambahkan semua sifat ke objek sekaligus.
Di sini, anda menggunakan notasi literal objek dan menambahkan kedua fungsi - calculateArea
dan calculateCircumference
(sekaligus) ke module.exports
objek dengan menulis satu pernyataan modul.eksport .
Sekiranya anda memeriksa output kod ini, anda akan mendapat hasil yang sama seperti yang anda dapatkan sebelumnya semasa menggunakan kaedah 1.
Kaedah 3:
(Menambah sifat ke module.exports
objek semasa menentukan konstruk)
Dalam kaedah ini, anda boleh menambahkan konstruk ke module.exports
objek sambil menentukannya. Mari lihat bagaimana kaedah ini dapat diguna pakai dalam circle
modul kami .
Dalam kod yang diberikan di atas, anda dapat melihat bahawa fungsi-fungsi dalam modul ditambahkan ke module.exports
objek ketika mereka ditentukan. Mari lihat bagaimana ini berfungsi. Anda menambah kunci calculateArea
ke module.exports
objek dan nilai yang sesuai dengan kunci ini adalah definisi fungsi.
Perhatikan bahawa fungsi tidak lagi mempunyai nama dan merupakan fungsi anonim yang hanya dianggap sebagai nilai pada kunci objek. Oleh itu, fungsi ini tidak dapat dirujuk dalam circle
modul dan anda tidak boleh menggunakan fungsi ini di dalam modul ini dengan menulis pernyataan berikut:
calculateArea(8);
Jika anda cuba untuk melaksanakan kenyataan di atas, anda akan mendapat ReferenceError
menyatakan calculateArea is not defined
.
Setelah anda mengetahui bagaimana anda dapat menentukan apa yang perlu dieksport dari modul, bagaimana anda fikir modul lain akan dapat menggunakan barang yang dieksport? Anda perlu mengimport modul ke beberapa modul lain agar dapat menggunakan barang yang dieksport dari yang pertama pada yang terakhir. Ini adalah ketika kita perlu membincangkan parameter lain bernama require
.
memerlukan
require
kata kunci merujuk kepada fungsi yang digunakan untuk mengimport semua konstruk yang dieksport menggunakan module.exports
objek dari modul lain. Sekiranya anda mempunyai modul x di mana anda mengeksport beberapa konstruk menggunakan module.exports
objek dan anda ingin mengimport konstruk yang dieksport ini dalam modul y , anda kemudian memerlukan modul x dalam modul y menggunakan require
fungsi tersebut. Nilai yang dikembalikan oleh require
fungsi dalam modul y sama dengan module.exports
objek dalam modul x .

Mari fahami ini menggunakan contoh yang telah kita bincangkan sebelumnya. Anda sudah mempunyai circle
modul dari mana anda mengeksport fungsi calculateArea
dan calculateCircumference
. Sekarang, mari kita lihat bagaimana anda boleh menggunakan require
fungsi untuk mengimport barang yang dieksport ke modul lain.
Mari buat dahulu fail baru di mana anda akan menggunakan kod yang dieksport dari circle
modul. Mari namakan fail ini app.js
dan anda boleh memanggilnya app
modul.
Objektifnya adalah untuk memasukkan ke dalam app
modul semua kod yang dieksport dari circle
modul. Jadi, bagaimana anda boleh memasukkan kod anda yang ditulis dalam satu modul di dalam modul yang lain?
Pertimbangkan sintaks require
fungsi yang diberikan di bawah:
const variableToHoldExportedStuff = require('idOrPathOfModule');
Yang require
fungsi mengambil masa dalam hujah yang boleh menjadi ID atau jalan. ID merujuk kepada id (atau nama) modul yang diperlukan. Anda harus memberikan ID sebagai hujah semasa anda menggunakan modul pihak ketiga atau modul teras yang disediakan oleh Pengurus Pakej Node. Sebaliknya, apabila anda mempunyai modul khusus yang ditentukan oleh anda, anda harus memberikan jalan modul sebagai hujah. Anda boleh membaca lebih lanjut mengenai fungsi memerlukan dari pautan ini.
Kerana anda sudah menentukan modul khusus yang dinamakan circle
, anda akan memberikan jalan sebagai argumen untuk require
fungsi tersebut.
app.js
Sekiranya anda melihat dengan jelas, titik di permulaan jalan bermaksud bahawa ia adalah jalan relatif dan modul app
dan circle
disimpan di jalan yang sama.
Mari log masuk ke konsol circle
pemboleh ubah, yang mengandungi hasil yang dikembalikan oleh require
fungsi. Mari lihat apa yang terdapat di dalam pemboleh ubah ini.
app.js
Periksa output dengan menyimpan semua kod anda dan jalankan perintah berikut di Terminal anda (yang terakhir tidak diperlukan jika anda sudah nodemon
memasang pakej):
node app
Pengeluaran:
{ calculateArea: [Function: calculateArea],calculateCircumference: [Function: calculateCircumference] }
Seperti yang anda lihat, require
fungsi mengembalikan objek, yang kuncinya adalah nama pemboleh ubah / fungsi yang telah dieksport dari modul yang diperlukan ( circle
). Ringkasnya, require
fungsi mengembalikan module.exports
objek.
Sekarang mari kita mengakses fungsi yang diimport dari circle
modul.
app.js
Pengeluaran:
Area = 200.96, Circumference = 50.24
Apa yang anda fikir akan berlaku jika saya cuba mengakses pemboleh ubah yang dinamakan PI
dalam circle
modul di dalam app
modul?
app.js
Pengeluaran:
Area = 200.96, Circumference = 50.24pi = undefined
Bolehkah anda memikirkan mengapa pi
adalah undefined
? Ini kerana pemboleh ubah PI
tidak dieksport dari circle
modul. Ingat titik di mana saya memberitahu anda bahawa anda tidak dapat mengakses kod yang ditulis di dalam modul di modul lain kerana semua kod yang ditulis di dalam modul adalah rahsia kecuali dieksport? Di sini, anda cuba mengakses sesuatu yang belum dieksport dari circle
modul dan bersifat peribadi untuknya.
Jadi, anda mungkin tertanya-tanya mengapa anda tidak mendapat ReferenceError
. Ini kerana anda cuba mengakses kunci yang dinamakan PI
di dalam module.exports
objek yang dikembalikan oleh require
fungsi. Anda juga tahu bahawa kunci yang dinamakan PI
tidak ada pada module.exports
objek.
Perhatikan bahawa semasa anda cuba mengakses kunci yang tidak ada dalam objek, anda akan mendapat hasilnya sebagai undefined
. Inilah sebab mengapa anda mendapat PI
dan undefined
bukannya mendapatkan ReferenceError
.
Sekarang, mari kita eksport pemboleh ubah PI
dari circle
modul dan lihat apakah jawapannya berubah.
bulatan.js
Perhatikan bahawa di sini, anda tidak menggunakan nama pemboleh ubah PI
sebagai kunci harta yang ditambahkan ke module.exports
objek. Anda sebaliknya menggunakan nama lain, iaitu lifeOfPi
.
Ini adalah perkara yang menarik untuk diperhatikan. Semasa anda mengeksport beberapa konstruksi pengkodan, anda boleh memberikan sebarang nama pada kunci semasa menambahkan harta yang ditambahkan ke module.exports
objek. Tidak wajib menggunakan nama yang sama dengan nama yang anda gunakan semasa menentukan konstruk. Ini kerana anda boleh menggunakan pengecam yang sah sebagai kunci dalam objek JavaScript. Oleh itu, di sebelah kiri operator penugasan, anda boleh menggunakan pengecam yang sah, tetapi di sebelah kanan operator penugasan, anda perlu memberikan nilai yang ditakrifkan sebagai konstruk dalam ruang lingkup modul semasa (seperti yang anda telah menentukan pemboleh ubah dan fungsi dalam modul 'bulatan').
Perkara penting yang perlu diberi perhatian ialah semasa mengimport sesuatu dari modul lain dalam modul semasa, anda perlu menggunakan kunci yang sama dengan yang anda gunakan semasa mengeksportnya.
app.js
Kerana anda menggunakan kunci lifeOfPi
, anda perlu menggunakan kunci yang sama untuk mengakses pemboleh ubah yang PI
ditentukan dalam circle
modul, seperti yang dilakukan dalam kod yang diberikan di atas.
Pengeluaran:
Area = 200.96, Circumference = 50.24pi = 3.14
Apa yang anda fikir akan berlaku jika anda menggunakan nama pembolehubah dan bukannya menggunakan kunci yang digunakan semasa mengeksport? Pendek kata, mari kita cuba mengakses PI
(nama pemboleh ubah) dan bukannya lifeOfPi
(kunci yang digunakan semasa mengeksport PI
).
app.js
Pengeluaran:
Area = 200.96, Circumference = 50.24pi = undefined
Ini berlaku kerana module.exports
objek tersebut tidak mengetahui pemboleh PI
ubahnya lagi. Ia hanya mengetahui tentang kunci yang ditambahkan kepadanya. Kerana kunci yang digunakan untuk mengeksport pemboleh ubah PI
adalah lifeOfPi
, yang terakhir hanya dapat digunakan untuk mengakses yang pertama.
TL; DR
- Setiap fail di Node.js disebut sebagai modul .
- Sebelum melaksanakan kod yang ditulis dalam modul, Node.js mengambil seluruh kod yang ditulis di dalam modul dan mengubahnya menjadi pembungkus fungsi, yang mempunyai sintaks berikut:
(function(exports, require, module, __filename, __dirname) { // entire module code lives in here});
- Pembungkus fungsi memastikan bahawa semua kod yang ditulis di dalam modul adalah miliknya kecuali dinyatakan sebaliknya (dieksport). Parameter
exports
,require
,module
,__filename
, dan__dirname
bertindak sebagai pembolehubah global kepada seluruh kod di dalam modul. Oleh kerana setiap modul mempunyai fungsi pembungkus sendiri, kod yang ditulis di dalam satu pembungkus fungsi menjadi lokal untuk pembungkus fungsi (modul baca) dan tidak dapat diakses di dalam pembungkus fungsi lain (modul baca). module
kata kunci merujuk kepada objek yang mewakili modul semasa. Themodule
objek mempunyai kunci dinamakanexports
.module.exports
adalah objek lain yang digunakan untuk menentukan apa yang dapat dieksport oleh modul dan dapat disediakan untuk modul lain. Ringkasnya, jika modul ingin mengeksport sesuatu, ia harus ditambahkan kemodule.exports
objek.- Nilai lalai
module.exports
objek adalah{}
. - Terdapat tiga kaedah di mana anda boleh mengeksport sesuatu dari modul, atau menambahkan sesuatu ke
module.exports
objek:1. Tentukan semua konstruk terlebih dahulu dan kemudian gunakan beberapa
module.exports
pernyataan di mana setiap pernyataan digunakan untuk mengeksport konstruk.2. Tentukan semua konstruk terlebih dahulu dan kemudian gunakan satu
module.exports
penyataan untuk mengeksport semua konstruk sekaligus mengikuti notasi literal objek.3. Tambahkan konstruk ke
module.exports
objek semasa menentukannya. require
kata kunci merujuk kepada fungsi yang digunakan untuk mengimport semua pemboleh ubah dan fungsi yang dieksport menggunakanmodule.exports
objek dari modul lain. Singkatnya, jika fail ingin mengimport sesuatu, ia mesti menyatakannya menggunakan sintaks berikut:
require('idOrPathOfModule');
- Semasa mengeksport sesuatu dari modul, anda boleh menggunakan pengecam yang sah. Anda tidak perlu memberikan nama sebenar pemboleh ubah / fungsi sebagai kunci harta yang ditambahkan ke
module.exports
objek. Pastikan anda menggunakan kunci yang sama untuk mengakses sesuatu yang anda gunakan semasa mengeksportnya.