4.4 מודולים תרגול
תרגול - מודולים¶
תרגיל 1 - ייצוא וייבוא בסיסיים¶
צרו שלושה קבצים:
stringUtils.js - מייצא (named) את הפונקציות הבאות:
- capitalize(str) - אות ראשונה גדולה
- reverse(str) - הופך מחרוזת
- countWords(str) - סופר מילים
mathUtils.js - מייצא (named) את הפונקציות הבאות:
- clamp(value, min, max) - מגביל ערך לטווח
- average(...numbers) - ממוצע
- isPrime(n) - בודק אם ראשוני
main.js - מייבא ומשתמש בכל הפונקציות:
// main.js
// import everything and use it:
console.log(capitalize("hello")); // "Hello"
console.log(reverse("abc")); // "cba"
console.log(countWords("hello world")); // 2
console.log(clamp(15, 0, 10)); // 10
console.log(average(1, 2, 3, 4)); // 2.5
console.log(isPrime(7)); // true
תרגיל 2 - ייצוא ברירת מחדל¶
צרו קובץ Logger.js שמייצא class כ-default export:
מחלקת Logger:
- constructor(prefix) - קידומת שתופיע בכל הודעה
- log(message) - מדפיס [PREFIX] message
- warn(message) - מדפיס [PREFIX] WARNING: message
- error(message) - מדפיס [PREFIX] ERROR: message
בנוסף, הקובץ מייצא named export של קבוע LOG_LEVELS:
כתבו את main.js שמייבא גם את ה-default וגם את ה-named export:
import Logger, { LOG_LEVELS } from "./Logger.js";
const logger = new Logger("App");
logger.log("Started"); // "[App] Started"
logger.warn("Low memory"); // "[App] WARNING: Low memory"
console.log(LOG_LEVELS.WARN); // "warn"
תרגיל 3 - barrel file¶
צרו מבנה תיקיות לפי המבנה הבא וכתבו barrel file שמרכז את כל הייצואים:
string.js - מייצא:
- isNotEmpty(str) - בודק שהמחרוזת לא ריקה
- hasMinLength(str, min) - בודק אורך מינימלי
number.js - מייצא:
- isPositive(n) - בודק שחיובי
- isInRange(n, min, max) - בודק שבטווח
email.js - מייצא:
- isValidEmail(str) - בודק פורמט אימייל בסיסי (מכיל @ ונקודה)
index.js - מייצא מחדש את הכל:
// usage from outside the validators folder:
import { isNotEmpty, isPositive, isValidEmail } from "./validators/index.js";
console.log(isNotEmpty("hello")); // true
console.log(isPositive(-5)); // false
console.log(isValidEmail("a@b.com")); // true
console.log(isValidEmail("not-an-email")); // false
תרגיל 4 - שינוי שמות בייבוא¶
נתון הקובץ הבא:
// helpers.js
export function format(value) {
return String(value).padStart(2, "0");
}
export function parse(str) {
return parseInt(str, 10);
}
export function validate(input) {
return input !== null && input !== undefined;
}
כתבו קובץ main.js שמייבא את כל שלוש הפונקציות עם שמות חדשים שמתארים את השימוש שלהן טוב יותר:
- format -> zeroPad
- parse -> toInt
- validate -> isDefined
בנוסף, כתבו ייבוא נוסף שמביא את הכל כאובייקט helpers.
תרגיל 5 - ייבוא דינמי¶
כתבו פונקציה loadModule(moduleName) שמטענת מודול דינמית לפי שם:
async function loadModule(moduleName) {
// your code here
}
// usage:
const module = await loadModule("math");
console.log(module.add(2, 3)); // 5
הפונקציה צריכה:
- לטעון את המודול מנתיב ./modules/${moduleName}.js
- להחזיר את המודול
- אם הטעינה נכשלת, להדפיס שגיאה ולהחזיר null
בנוסף, כתבו פונקציה loadOnClick(buttonId, moduleName) שטוענת מודול רק כשלוחצים על כפתור:
function loadOnClick(buttonId, moduleName) {
// your code here - load the module only on first click
}
תרגיל 6 - מערכת פלאגינים עם מודולים¶
צרו מערכת פשוטה שטוענת "פלאגינים" דינמית. כל פלאגין הוא מודול עם המבנה הבא:
// plugins/uppercase.js
export const name = "uppercase";
export const description = "Converts text to uppercase";
export function execute(input) {
return input.toUpperCase();
}
צרו שלושה פלאגינים:
1. uppercase.js - ממיר לאותיות גדולות
2. reverse.js - הופך מחרוזת
3. wordcount.js - מחזיר את מספר המילים
צרו class PluginManager שמנהל את הפלאגינים:
- async loadPlugin(name) - טוען פלאגין דינמית מתיקיית ./plugins/
- listPlugins() - מחזיר רשימת פלאגינים טעונים (שם + תיאור)
- run(pluginName, input) - מריץ פלאגין על input
const manager = new PluginManager();
await manager.loadPlugin("uppercase");
await manager.loadPlugin("reverse");
console.log(manager.listPlugins());
// [{ name: "uppercase", description: "..." }, { name: "reverse", description: "..." }]
console.log(manager.run("uppercase", "hello")); // "HELLO"
console.log(manager.run("reverse", "hello")); // "olleh"