Minden, amit tudnia kell a Node.js 'modulról' és a 'szükségességéről'

Modulok

A Node.js minden egyes JavaScript fájlt külön modulként kezel.

Például, ha van egy fájl, amely valamilyen kódot tartalmaz, és ezt a fájlt elnevezik xyz.js, akkor ezt a fájlt modulként kezeljük a Node-ban, és mondhatjuk, hogy létrehoztunk egy nevű modult xyz.

Vegyünk egy példát, hogy ezt jobban megértsük.

Van egy fájlja, circle.jsamely az adott sugarú kör területének és kerületének kiszámításához szükséges logikából áll, az alábbiak szerint:

kör.js

Hívhatja a circle.jsfájlt nevű modulnak circle.

Kíváncsi lehet, miért van szükség több modulra? Csak beírhatta az összes kódot egyetlen modulba. Nos, nagyon fontos moduláris kódot írni. Moduláris alatt azt akarom mondani, hogy a kódjának függetlennek és lazán összekapcsoltnak kell lennie. Képzelje el, hogy van egy nagy alkalmazás, és az összes kódot csak egy helyre, csak egy fájlba írja. Túl rendetlen, igaz?

Hogyan fut a modulba írt kód?

Mielőtt végrehajtaná a modulba írt kódot, a Node átveszi a teljes kódot, és bezárja egy függvény burkolóba. Ennek a funkcióburkolónak a szintaxisa:

A circlemodul funkcióburkolója az alábbiak szerint fog kinézni:

Láthatja, hogy a gyökér szintjén van egy funkció burkoló, amely felöleli a circlemodulba írt összes kódot .

A modul belsejébe írt teljes kód privát a modullal szemben, hacsak kifejezetten másként nem állítjuk (exportáljuk).

Ez a legjelentősebb előnye annak, ha a modulok a Node.js-ben vannak. Még akkor is, ha globális változót definiál egy modulban var, letvagy constkulcsszavak használatával, a változók lokálisan a modulra terjednek ki, nem pedig globálisan. Ez azért történik, mert minden modulnak van egy saját funkcióburkolója, és az egyik függvénybe beírt kód lokális ennek a függvénynek, és nem érhető el ezen a függvényen kívül.

Képzeljük el, hogy van két modul - A és B . A kódot írt belsejében modul van zárva a funkciót wrapper megfelelő modul . Hasonló történik a B modulba írt kóddal . Mivel a mindkét modulhoz tartozó kód különféle funkciókba van foglalva, ezek a funkciók nem fogják tudni elérni egymás kódját. (Ne feledje, hogy a JavaScript minden egyes funkciójának megvan a maga helyi hatóköre?) Ez az oka annak, hogy az A modul nem tud hozzáférni a B modulba írt kódhoz, és fordítva.

Az öt paraméter - exports, require, module, __filename, __dirnameállnak belül minden modul csomópont. Bár ezek a paraméterek globálisak a modulban található kódhoz képest, mégis lokálisak a modulhoz (a függvény burkolójának a fentiekben leírtak miatt). Ezek a paraméterek értékes információkat nyújtanak a modullal kapcsolatban.

Nézzük át a circlemodult, amelyet korábban megnézett. Ebben a modulban három konstrukció van meghatározva - egy állandó változó PI, egy megnevezett függvény calculateAreaés egy másik függvény megnevezve calculateCircumference. Fontos szem előtt tartani, hogy ezek a konstrukciók circlealapértelmezés szerint privátak a modulhoz. Ez azt jelenti, hogy ezeket a konstrukciókat csak kifejezetten megadva használhatja más modulokban.

Tehát a most felmerülő kérdés az, hogy hogyan adhat meg valamit egy modulban, amelyet más modul használhat? Ekkor hasznosak a függvénytörlő module& requireparaméterei. Beszéljük meg ezt a két paramétert ebben a cikkben.

module

A moduleparaméter (inkább egy kulcsszó a modulban a Node-ban) az aktuális modult képviselő objektumra vonatkozik . exportsaz moduleobjektum kulcsa , amelynek megfelelő értéke egy objektum. Az module.exportsobjektum alapértelmezett értéke {}(üres objektum). Ezt úgy ellenőrizheti, hogy a modulekulcsszó értékét bármely modulban naplózza . Ellenőrizzük, hogy mekkora a moduleparaméter értéke a circlemodulban.

kör.js

Figyelje meg, hogy a console.log(module);fenti fájlban található egy kód a kód végén. Amikor látja a kimenetet, naplózza az moduleobjektumot, amelynek van egy neve megnevezett kulccsal, exportsés ennek a kulcsnak megfelelő értéke {}(üres objektum).

Most mit csinál az module.exportsobjektum? Nos, a modul által exportálható dolgok meghatározására szolgál. Bármi, amit egy modulból exportálnak, az más modulok számára elérhetővé válhat. Valamit exportálni meglehetősen egyszerű. Csak hozzá kell adnia az module.exportsobjektumhoz. Háromféleképpen adhat hozzá valamit az module.exportsexportálandó objektumhoz. Beszéljük meg ezeket a módszereket egyenként.

1. módszer:

(Konstrukciók definiálása, majd több module.exportsutasítás használata tulajdonságok hozzáadásához)

Az első módszerben először definiálja a konstrukciókat, majd több modul.exports állítást használ, ahol az egyes utasításokat valamilyen modulból exportálják. Nézzük meg ezt a módszert működés közben, és nézzük meg, hogyan lehet exportálni a circlemodulban definiált két függvényt .

kör.js

Amint azt korábban elmondtam, moduleegy olyan objektum, amelynek a kulcsa meg van nevezve, exportsés ez a kulcs ( module.exports) viszont egy másik objektumból áll. Most, ha észreveszi a fent megadott kódot, csak annyit tesz, hogy új tulajdonságokat (kulcs-érték párokat) ad hozzá az module.exportsobjektumhoz.

Az első tulajdonságban van a kulcs calculateArea(a 19. soron definiálva)és a hozzárendelés operátor jobb oldalára írt érték a névvel meghatározott funkció calculateArea(a 9. sorban).

A második tulajdonság (amelyet a 20. sor határoz meg) rendelkezik a kulccsal calculateCircumferenceés az érték a névvel definiált függvény calculateCircumference(a 16. sorban).

Így két tulajdonságot (kulcs-érték pár) rendelt az module.exportsobjektumhoz.

Ne felejtsük el azt sem, hogy itt a pontjelölést használtad. Alternatív megoldásként használhatja a zárójel jelölést a tulajdonságok hozzárendeléséhez az module.exportsobjektumhoz, és hozzáadhatja a függvényeket - calculateAreaés calculateCircumferencea zárójel jelölést követő kulcsok megadásával. Így a következő két sort megírhatja tulajdonságok hozzáadásához az module.exportsobjektumhoz zárójeles jelölés használatával, miközben az előző két sort helyettesíti (pontjelöléssel) a fent megadott kódban:

// exporting stuff by adding to module.exports object using the bracket notation
module.exports['calculateArea'] = calculateArea;module.exports['calculateCircumference'] = calculateCircumference; 

Most próbáljuk meg naplózni az module.exportsobjektum értékét a tulajdonságok hozzáadása után. Vegye figyelembe, hogy az alábbi állítás a kód végén található az alábbi fájlban:

// logging the contents of module.exports object after adding properties to it
console.log(module.exports);

kör.js

Ellenőrizzük ennek a kódnak a kimenetét, és nézzük meg, hogy minden jól működik-e. Ehhez mentse el a kódot, és futtassa a következő parancsot a terminálon :

node circle

Kimenet:

{ calculateArea: [Function: calculateArea], calculateCircumference: [Function: calculateCircumference] }

A konstrukciókat - calculateAreaés calculateCircumferenceaz module.exportsobjektumhoz hozzáadva - naplózza. Így sikeresen hozzáadta a két tulajdonságot az module.exportsobjektumba, így a függvények - calculateAreaés calculateCircumferenceexportálhatók a circlemodulból egy másik modulba.

Ebben a módszerben először definiálta az összes konstrukciót, majd több modul.export parancsot használt, ahol minden utasítással tulajdonságot adnak az module.exportsobjektumhoz.

2. módszer:

(Konstrukciók meghatározása, majd egyetlen module.exportsutasítás használata tulajdonságok hozzáadásához)

Egy másik módszer az, hogy először definiáljuk az összes konstrukciót (ahogyan azt a korábbi módszerben tettük), de egyetlen module.exportsutasítással exportálhatjuk őket. Ez a módszer hasonlít az objektum szó szerinti jelölés szintaxisához, ahol az összes tulajdonságot egyszerre adja hozzá egy objektumhoz.

Itt az objektum szó szerinti jelölést használta, és mind a függvényeket - calculateArea mind calculateCircumference(egyszerre) hozzáadta az module.exportsobjektumhoz egyetlen modul.exports utasítás megírásával .

Ha ellenőrzi ennek a kódnak a kimenetét, akkor ugyanazt az eredményt kapja, mint amit korábban kapott az 1. módszer használatakor.

3. módszer:

(Tulajdonságok hozzáadása az module.exportsobjektumhoz a konstrukciók definiálása közben)

Ebben a módszerben hozzáadhatja a konstruktumokat az module.exportsobjektumhoz, miközben meghatározza azokat. Lássuk, hogyan alkalmazható ez a módszer a circlemodulunkban.

A fent megadott kódban láthatja, hogy a modulban található függvények module.exportsdefiniáláskor hozzáadódnak az objektumhoz. Nézzük meg, hogyan működik ez. Kulcsot calculateAreaad hozzá az module.exportsobjektumhoz, és ennek a kulcsnak megfelelő érték a függvénydefiníció.

Vegye figyelembe, hogy a függvénynek már nincs neve, és névtelen függvény, amelyet csak egy objektum kulcsának értékeként kezelnek. Így erre a függvényre nem lehet hivatkozni a circlemodulban, és nem hívhatja meg ezt a függvényt a modulon belül a következő utasítás megírásával:

calculateArea(8);

Ha megpróbálja végrehajtani a fenti állítást, akkor kap egy ReferenceErrornyilatkozatot calculateArea is not defined.

Most, hogy megtanulta, hogyan adhatja meg, hogy mit kell exportálni egy modulból, mit gondol, hogyan fogja tudni használni a másik modul az exportált anyagokat? Importálnia kell a modult valamilyen más modulba, hogy az előbbiből exportált anyagokat az utóbbiban tudja használni. Ekkor meg kell vitatnunk egy másik nevű paramétert require.

megkövetelik

requirekulcsszó egy olyan függvényre utal, amely az module.exportsobjektum segítségével exportált összes konstrukció importálására szolgál egy másik modulból. Ha van olyan x modulod , amelyben néhány konstrukciót exportálsz az module.exportsobjektum segítségével, és ezeket az exportált konstrukciókat az y modulba akarod importálni , akkor a függvény használatával meg kell követelned az x modult az y modulban require. Az yrequire modulban a függvény által visszaadott érték megegyezik az x modulban levő objektummal .module.exports

Értsük meg ezt a korábban tárgyalt példán keresztül. Már megvan a circlemodul, amelyből exportálja a függvényeket calculateAreaés calculateCircumference. Most nézzük meg, hogyan használhatja a requirefüggvényt az exportált dolgok importálásához egy másik modulba.

Először hozzunk létre egy új fájlt, amelyben a circlemodulból exportált kódot fogja használni . Nevezzük el ezt a fájlt, app.jsés hívhatjuk appmodulnak.

A cél a appmodulból exportált összes kód importálása a circlemodulba. Szóval, hogyan lehet az egyik modulba írt kódját beilleszteni egy másik modulba?

Vegye figyelembe az requirealább megadott szintaxist :

const variableToHoldExportedStuff = require('idOrPathOfModule');

A requirefüggvény olyan argumentumot vesz fel, amely lehet azonosító vagy elérési út. Az azonosító a szükséges modul azonosítójára (vagy nevére) utal. Meg kell adnia az azonosítót argumentumként, amikor a Node Package Manager által biztosított külső modulokat vagy alapvető modulokat használja. Másrészt, ha egyéni modulokat határoz meg, akkor meg kell adnia argumentumként a modul elérési útját. Erről a linkről többet tudhat meg a szükséges funkcióról.

Mivel már definiált egy nevű egyéni modult circle, a requirefüggvény argumentumaként megadja az elérési utat .

app.js

Ha világosan észreveszi, a pont az útvonal elején azt jelenti, hogy ez egy relatív útvonal, és hogy a modulok appés circleugyanazon az úton vannak tárolva.

Jelentkezzünk be a konzolba a circleváltozóba, amely tartalmazza a requirefüggvény által visszaadott eredményt . Lássuk, mit tartalmaz ez a változó.

app.js

Ellenőrizze a kimenetet az összes kód elmentésével és a következő parancs futtatásával a terminálban (ez utóbbi nem szükséges, ha nodemontelepítve van a csomag):

node app

Kimenet:

{ calculateArea: [Function: calculateArea],calculateCircumference: [Function: calculateCircumference] }

Amint láthatja, a requirefüggvény egy olyan objektumot ad vissza, amelynek kulcsai a szükséges modulból ( circle) exportált változók / függvények nevei . Röviden: a requirefüggvény visszaadja az module.exportsobjektumot.

Most nyissuk meg a circlemodulból importált függvényeket .

app.js

Kimenet:

Area = 200.96, Circumference = 50.24

Szerinted mi fog történni, ha megpróbálom elérni PIa circlemodulban definiált változót a modul belsejében app?

app.js

Kimenet:

Area = 200.96, Circumference = 50.24pi = undefined

Tud kitalálni, hogy miért pivan undefined? Nos, ez azért van, mert a változót PInem exportálják a circlemodulból. Emlékezzen arra a pontra, ahol azt mondtam, hogy nem férhet hozzá a modulba írt kódhoz egy másik modulban, mivel az összes kód, amelyet egy modulba írtak, csak akkor exportálható, ha exportálják? Itt olyasmihez próbál hozzáférni, amelyet nem exportáltak a circlemodulból, és amely privát hozzá tartozik.

Szóval, azon gondolkodhat, miért nem kapott a ReferenceError. Ennek oka az, hogy megpróbál elérni egy kulcsot, amelyet a függvény által visszaadott objektumon PIbelül neveznek module.exportsel require. Azt is tudja, hogy a megnevezett kulcs PInem létezik az module.exportsobjektumban.

Vegye figyelembe, hogy amikor egy objektumban nem létező kulcshoz próbál hozzáférni, akkor az eredményt így kapja undefined. Ez az oka annak, hogy kapsz, PImint undefinedahelyett, hogy a ReferenceError.

Most exportáljuk a változót PIa circlemodulból, és nézzük meg, változik-e a válasz.

kör.js

Figyelje meg, hogy itt nem a változó nevét használja PIaz module.exportsobjektumhoz hozzáadott tulajdonság kulcsaként . Ehelyett másik nevet használ, ami lifeOfPi.

Érdekes megjegyezni ezt. Ha valamilyen kódoló konstrukciót exportál, az module.exportsobjektumhoz hozzáadott tulajdonság hozzáadásakor bármilyen nevet adhat a kulcsnak . A konstrukció meghatározása során nem kötelező ugyanazt a nevet használni. Ez azért van, mert bármilyen érvényes azonosítót használhat kulcsként egy JavaScript-objektumban. Így a hozzárendelés operátor bal oldalán bármilyen érvényes azonosítót használhat, de a hozzárendelés operátor jobb oldalán meg kell adnia egy értéket, amelyet konstrukcióként definiálnak az aktuális modul hatókörében (ahogy Ön meghatároztuk a változókat és a függvényeket a „kör” modulban).

Fontos megjegyezni, hogy miközben importál valamit az aktuális modul másik moduljából, ugyanazt a kulcsot kell használnia, amelyet az exportálásakor használt.

app.js

Mivel a kulcsot használtad lifeOfPi, ugyanazt a kulcsot kell használnod PIa circlemodulban definiált változó eléréséhez , ahogyan azt a fent megadott kód is teszi.

Kimenet:

Area = 200.96, Circumference = 50.24pi = 3.14

Szerinted mi fog történni, ha az exportáláskor használt kulcs helyett a változó nevét használod? Röviden, próbáljuk meg elérni PI(a változó neve) az lifeOfPi(exportáláskor használt kulcs ) helyett PI.

app.js

Kimenet:

Area = 200.96, Circumference = 50.24pi = undefined

Ez azért történik, mert az module.exportsobjektum már nem ismeri a változót PI. Csak tud a hozzá adott kulcsokról. Mivel a változó exportálásához használt kulcs PIaz lifeOfPi, az utóbbi csak az előbbihez használható.

TL; DR

  • A Node.js minden fájlját modulnak nevezzük .
  • A modulba írt kód végrehajtása előtt a Node.js elveszi a modul belsejébe írt teljes kódot, és átalakítja azt egy funkció burkolóvá, amelynek a következő szintaxisa van:
(function(exports, require, module, __filename, __dirname) { // entire module code lives in here});
  • A függvény burkolója biztosítja, hogy a modulon belül beírt összes kód privát legyen, hacsak kifejezetten másként nem exportálták (exportálták). A paraméterek exports, require, module, __filename, és __dirnameúgy járnak, mint a változók globális az egész kódot egy modult. Mivel mindegyik modulnak van egy saját funkcióburkolója, az egyik funkcióburkolóba beírt kód lokálissá válik az adott funkcióburkolóhoz (olvasási modul), és nem érhető el egy másik függvényburkolóban (olvasási modul).
  • modulekulcsszó az aktuális modult képviselő objektumra utal. Az moduleobjektumnak van egy neve exports. module.exportsegy másik objektum, amely meghatározza, hogy mi exportálható egy modul által, és elérhetővé tehető más modulok számára. Röviden, ha egy modul exportálni akar valamit, akkor hozzá kell adni az module.exportsobjektumhoz.
  • Az module.exportsobjektum alapértelmezett értéke {}.
  • Három módszer létezik, amelyekkel exportálhat valamit egy modulból, vagy hozzáadhat valamit az module.exportsobjektumhoz:

    1. Először határozza meg az összes konstrukciót, majd használjon több module.exportsutasítást, ahol az egyes utasításokat egy konstrukció exportálásához használják.

    2. Először definiálja az összes konstrukciót, majd egyetlen module.exportsutasítással exportálja az összes konstrukciót egyszerre az objektum szó szerinti jelölés alapján.

    3. Adjon konstruktumokat az module.exportsobjektumhoz, miközben definiálja azokat.

  • requirekulcsszó egy olyan függvényre utal, amely az module.exportsobjektum használatával exportált összes változó és függvény importálására szolgál egy másik modulból. Röviden, ha egy fájl importálni akar valamit, akkor azt a következő szintaxissal kell deklarálnia:
require('idOrPathOfModule');
  • Miközben exportál valamit egy modulból, bármilyen érvényes azonosítót használhat. Nem kötelező megadni a változó / függvény pontos nevét az module.exportsobjektumhoz hozzáadott tulajdonság kulcsaként . Csak győződjön meg arról, hogy ugyanazt a kulcsot használja valamilyen fájl eléréséhez, amelyet exportálásakor használt.