לדלג לתוכן

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:

export const LOG_LEVELS = {
    INFO: "info",
    WARN: "warn",
    ERROR: "error"
};

כתבו את 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 שמרכז את כל הייצואים:

validators/
  index.js          <-- barrel file
  string.js
  number.js
  email.js

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"