
exports: האובייקט שדרכו חושפים דברים החוצה.require: פונקציה לייבוא מודולים אחרים.module: אובייקט עם מידע על המודול הנוכחי, ובתוכו המאפיין exports.__filename: הנתיב המלא של הקובץ.__dirname: הנתיב של התיקייה שבה הקובץ נמצא.var ו-function נכנסים לאובייקט הגלובלי window, ולכן מתכנתים שונים דורסים זה את זה. ב-Node.js לכל קובץ יש סקופ משלו.module.exports, למשל module.exports.num.require, עם נתיב יחסי כמו require('./my-first-module').הטקסט המלא של הדקות הראשונות בהרצאה «הסבר על מודול ב-node.js» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
אנחנו מגיעים לקונספט מאוד בסיסי ומאוד חשוב ב-Node.js שנקרא Modules. בואו נבין מה זה מודול. אז מודול זה פשוט מאוד קובץ source code אחד שאנחנו כותבים ב-Node.js.
כל קובץ שאנחנו מוסיפים הוא אוטומטית נחשב מודול. אבל למה נתנו לו בעצם את השם הזה מודול כאילו שזה יחידה נפרדת?
כי יש עוד משהו ש-Node.js מבצעת עבור כל קובץ שאנחנו עובדים עליו. אז כמו תמיד אנחנו מוסיפים Up.js ומיד נבנה לעצמנו npm init -y ואז המערכת תבנה לנו את הקובץ package.json עם כל ההגדרות הדפולטיות ויש לנו כרגע קובץ אחד ויחיד אפ ג'י אס וכאשר אנחנו רוצים בעצם להריץ אותו אז אנחנו רושמים נוד אפ והוא רץ.
דבר ראשון, הקובץ הראשון שמורץ נקרא מיין מודול. אז אם אנחנו מבחינתנו האפ ג'י אס זה הקובץ שאנחנו רוצים שהוא ירוץ ראשון וכמובן חייב להיות לנו קובץ אחד כזה שהוא הראשון שרץ, אנחנו לא יכולים לומר למערכת יש לי פה שניים או שלושה קבצים, להריץ אותם ראשונים אז יש לנו כאן את המיין מודול אם אנחנו עכשיו מוסיפים כל קובץ נוסף בואו נוסיף my first
module js אז יש לנו קובץ שהוא נפרד לגמרי והוא נחשב מודול בפני עצמו אנחנו יכולים לכתוב בו קוד ולהשתמש איתו בקבצים אחרים אבל לפני שנעשה את זה בואו נבין רגע מה Node.js מוסיפה לקובץ הזה בצורה אוטומטית, שזה משהו שלא קיים ב-JavaScript הרגילה שמורצת בדפדפן.
אז אם אתם טיפה מכירים JavaScript מעולם ה-Clientside הדפדפנים, יש משהו שנקרא Immediately Invoked Function Expression או EFI.
לפעמים קוראים לזה גם Self-Invoke Function, לפעמים קוראים לזה Self-Executing Function, יש לזה כל מיני שמות, אבל השם הכי נפוץ זה EFI, והשם שרואים אותו הכי הרבה ברשת, ב-Stack Overflow וכאלה.
ומה שזה עושה, אנחנו פשוט הרבה פעמים, כשאנחנו כותבים JavaScript ב-Client Side, אנחנו כותבים דבר כזה, פונקשן פותחים כאן איזושהי פונקציה סוגרים אותה עוטפים אותה בסוגריים כאלה ושוב פעם קוראים לפונקציה כלומר כאן יש את הקריאה בעצם לפונקציה שאנחנו כותבים כאן ושימו לב שזאת אינליין פונקשן
אין לה שם לפונקציה הזאת עכשיו למה אנחנו עושים את הדבר הזה בג'אווה סקריפט קליינט סייד ב-JavaScript Client Site שמורצת בדפדפן יש לנו איזשהו אובייקט גלובלי שנקרא ווינדואו.
וכל פעם ב-JavaScript שאנחנו כותבים לדוגמה var x אז הוא אוטומטית משוייך לווינדואו. כל פעם ב-JavaScript כשאנחנו כותבים function f כלשהי, אוטומטית הפונקציה עוד שייכת לווינדואו.
וב-JavaScript זה דבר לא טוב, אני מדבר על JavaScript שמורצת ב-Client Site, כלומר, מורצת בדפדפן. זה לא טוב לצרף דברים לווינדו, מפני שהווינדו נגיש בכל האתר, בכל האפליקציה, בכל ה-Client Side.
זאת אומרת, אם יש לנו כמה מתכנתים, נניח, שעובדים על האתר, וכל מתכנת כותב כובד JavaScript בפני עצמו משלו, אז כל מתכנת יכול לבנות פונקציה שנקראת F לדוגמה, אולי F זה שם קצת פחות משמעותי, אבל פונקציה שנקראת לדוגמה Get Average, בכדי לקבל איזשהו מערך ולהחזיר את הממוצע שלו.
אבל בגלל שכל הפונקציות האלה משויכות לווינדואו, כל אחד ידרוס את הפונקציה של השני. הסקריפט האחרון שיטען ידרוס את כל הפונקציות הקודמות, ויש לנו פה כמובן בלאגן ובאגים.
מה גם שלפעמים אני לא רוצה לחשוף פונקציה לכל המתכנתים, אני רוצה אותה באופן פרטי רק עבור הצרכים שלי. לכן הרבה פעמים הדבר הנכון לבצע ב-JavaScript שנמצאת בדפדפן, זה את הקטע קוד הזה שנקרא ify.
Immediately Invoked Function Expression, שמה שהוא עושה הוא פשוט מכיל פונקציה עטופה בסוגריים ולכן היא לא שייכת לאובייקט הגלובלי, ומיד אנחנו מפעילים אותה פעם אחת לכדי שהיא תריץ ותבצע את מה שיש בתוכה.
כל מה שעכשיו אנחנו כותבים בתוך הפונקציה הזאת לא שייך ל-Window. שוב, אני לא מדבר על Node.js, אני מדבר על דפדפן רגיל שבו אנחנו כותבים JavaScript. ואם אנחנו כותבים איזושהי פונקציה, אז הפונקציה הזאת לא שייכת ל-Window, היא שייכת רק לקובץ הנוכחי.
את זה הרבה פעמים אנחנו עושים כשאנחנו כותבים Client-Side JavaScript. אוקיי, למה חשוב לנו להכיר את הקונספט הזה? הרי אנחנו לא כותבים כרגע JavaScript שמורצת בדפדפן.
מפני שהקונספט הזה הוא כל כך נכון לביצוע ש-Node.js בין אם אנחנו רוצים ובין אם אנחנו לא רוצים אוטומטית עושה את זה עבור כל קובץ JavaScript שאנחנו מוסיפים.
גם ל-Main מודול וגם לכל קובץ Source Code אחר Node.js עושה את זה אבל לא בדיוק מה שאנחנו רואים כאן אלא פונקציה מיוחדת שמקבלת חמישה ארגומנטים לסוגריים. וארגומנטים שאוטומטית נשלחים לפונקציה הזאת הם ארגומנט ראשון נקרא exports, ארגומנט שני נקרא require, ארגומנט שלישי נקרא module, ארגומנט רביעי נקרא underline, underline,
file name, וארגומנט חמישי נקרא underline, underline, dear name. אלה חמישה ארגומנטים שבעצם Node.js Node.js אוטומטית מקבלת אותם ל-Eפי ובגלל שזאת הקריאה ל-Eפי, Node.js אוטומטית כותבת פה קטע קוד, הופה, יותר מדי נקודות עשיתי, ששולח ערכים מתאימים למשתנים האלה.
אנחנו, כשאנחנו מתכנתים Node.js, בגלל שבכל קובץ שאנחנו בונים אוטומטית יש את הדבר הזה, שימו לב, אנחנו לא צריכים לכתוב את זה ואנחנו גם לא כותבים את זה.
זה אוטומטית קיים, חשוב לנו מאוד להבין מה זה הדברים האלה שקיימים לנו עכשיו לשימוש בכל קובץ, מבלי שאנחנו אפילו רואים אותם.
אז לפני שנצלול פנימה ונראה מה זה חמשת הדברים האלה, קודם כל נבין שהדבר הזה הוא אוטומטית קיים בכל קובץ.
אז אני כרגע אשים את זה רק בהערה כאן כדי שנבין שכשאנחנו עכשיו כותבים פה קטע קוד, חמשת הארגומנטים האלה זמינים לנו. אז דבר ראשון זה משהו שמתבצע עבור כל קובץ JavaScript שאנחנו כותבים.
אוקיי, בסדר, אז בואו רגע נראה כמה דברים מעניינים לגבי זה. נעתיק את זה גם לכאן, רק בשביל שזה יהיה לנו מול העיניים.
נשים גם את הקטע קוד הזה, רק בכדי שנבין שזה משהו שקיים לנו כל הזמן, ונדפיס קודם כל את ה-underline-underline-file-name. בואו נריץ את האפליקציה שבנינו, Node-App, ושימו לב שאנחנו מקבלים ב-file-name את הקובץ הנוכחי.
אם אנחנו כרגע הרצנו את ה-app.js זה בעצם מה שאנחנו מקבלים, הקובץ הנוכחי שאנחנו כרגע נמצאים בו. אם אני מה-app.js אקרא ל-My First Model, או יטען אותו, אז כמובן שה-underline underline file name פה יהיה my first module.
שימו לב שזה כולל את כל הנתיב איפה שהקובץ הזה נמצא. עוד לא הראתי איך אני טוען מודול אחר, תכף אנחנו נראה את זה. אוקיי, אז כמו שיש לנו את ה-console log הראשון, בואו נדפיס גם את dear name.
נריץ את זה, ונראה ש-dear name מאוד דובר ל-file name, זה פשוט הנתיב של התיקייה הנוכחית, איפה הקובץ הזה כרגע נמצא. יכול להיות שהוא נמצא בכל מיני תתי תיקיות שיש לי באפליקציה, אז כמובן ה-dear name יהיה כל הנתיב מההתחלה כולל תתי התיקיות עד לקובץ הנוכחי.
אז זה מאוד פשוט להבין את שני החבר'ה האלה. בואו נבין מה זה exports ומה זה מודול, ואז נבין מה זה require. נעשה קודם כל, נבין מה זה מודול ואז אקספורטס.
לצורך כך אני עובר לקובץ My First Module. אז האובייקט מודול שנשלח אלינו לכאן, בואו רגע האמת, נדפיס אותו קודם כל, נבצע console.log, אני חוזר רגע ל-app כי app אוטומטית רצה לי כאשר אני מריץ את האפליקציה, אני תמיד מריץ קודם כל את app אז מאוד קל לראות את זה מודול אפשר להוריד את
שני החבר'ה האלה נריץ שוב פעם ונראה שמודול ואיזשהו אובייקט שמכיל כל מיני אינפורמציה על המודול הנוכחי אנחנו רואים קודם כל שיש כאן את הפייל ניים שוב פעם אנחנו רואים האם יש לו צ'ילדרן כל מיני נתיבים שהוא מכיר ומשהו מעניין אנחנו רואים אובייקט שנקרא אקספורט והאובייקט הזה הוא אובייקט ריק.
ולמעשה האובייקט exports שנמצא בתוך המודול זה המשתנה exports הזה. זאת אומרת ש-node.js שולחת את האובייקט המלא מודול לכאן, שוב הוא מחזיק אינפורמציה ספציפית לגבי המודול הנוכחי, ואת המאפיין exports שלו היא שוב פעם שולחת כאן כפרמטר ראשון.
אז זה בעצם משהו שהוא מאוד מעניין, ואנחנו תמיד עושים שימוש, הרבה פעמים עושים שימוש באקספורטס. והאקספורטס פשוט מאוד מאפשר לחשוף החוצה מתוך המודול, כלומר מתוך הקובץ הזה, מה שאנחנו רוצים שיהיה נגיש מבחוץ.
מה הכוונה? אם אני כרגע אבצע פה איזשהו משתנה var x שווה 10, האם המשתנה הזה עכשיו נגיש אוטומטית מחוץ למודול הזה?
והתשובה היא לא, המשתנה הזה לא נגיש, למה? מפני שבדיוק כמו ב-JavaScript Client Side הוא נמצא בתוך אפי ולכן הוא לוקאלי לגבי הפונקציה הזאת וזה אומר שהוא לוקאלי לגבי המודול.
הדבר הזה לוקאל. אם אני עכשיו בונה איזושהי פונקציה fconsole.log Do something, האם הפונקציה הזאת אוטומטית נגישה מחוץ למודול?
תשובה, לא. פונקציה הזאת נמצאת בתוך הפונקציה העוטפת, בתוך ה-Eפי, ב-JavaScript זה כמובן דבר שמותר לביצוע, והיא לא חשופה החוצה, היא לוקאלית לגבי ה-Eפי, כלומר לגבי המודול.
כי ה-Eפי הזה אוטומטית קיים אצלנו על ידי Node.js, Node.js אוטומטית מצרפת אותו. אוקיי, אז אם אני כן רוצה לחשוף איזשהו משתנה או איזושהי פונקציה החוצה מתוך המודול שלי, אני יכול להשתמש באובייקט מודול שנשלח אליי, בתוכו יש את xPorts ואז בתוך xPorts אני יכול לבנות איזה משתנים שאני רוצה.
ב-JavaScript אם אני, בואו נעשה פה איזה משתנה שנקרא num, אם אני עכשיו יוצר משתנה חדש בתוך אובייקט מבלי שהוא יהיה קיים, JavaScript מוסיפה אותו לאובייקט.
זה כמובן חלק משפת JavaScript. אז הנה יש לנו כאן עכשיו איזשהו משתנה שנקרא num, בואו נלך ל-module.exports ונבנה איזושהי פונקציה, do work, ונכניס כאן function, doing some work, וחשפנו החוצה כרגע, שני אלמנטים, איזשהו
משתנה אינטג'רי, או ליתר דיוק מספרי, ויש לנו כאן פונקציה. בואו נחשוף module.exports ונחשוף איזשהו אובייקט.