ماژولها (Modules)
Module چیست، ES Modules با export و import، Default و Named Export، Dynamic Import، Module Scope، CommonJS و مدیریت وابستگیها.
Module چیست؟
ماژول فایلی است که کد را کپسوله میکند — هر فایل Scope خودش را دارد:
// بدون ماژول — همه در глобال: ❌
// script1.js: var name = "علی";
// script2.js: var name = "سارا"; // تداخل!
// با ماژول — ایزوله: ✓
// هر فایل جدا، import/export برای ارتباط
ES Modules در مرورگر
<!-- type="module" الزامی: -->
<script type="module" src="app.js"></script>
<!-- یا inline: -->
<script type="module">
import { greet } from "./utils.js";
console.log(greet("علی"));
</script>
ماژولها: خودکار Strict Mode، فقط یکبار اجرا (Singleton)، defer دارند.
Named Export — خروجی نامدار
// utils.js — چند خروجی:
export const PI = 3.14159;
export function circleArea(r) {
return PI * r ** 2;
}
export class Calculator {
add(a, b) { return a + b; }
}
// یا یکجا در انتها:
const multiply = (a, b) => a * b;
const divide = (a, b) => b !== 0 ? a / b : null;
export { multiply, divide };
Named Import
// import با همان نام:
import { PI, circleArea, Calculator } from "./utils.js";
console.log(PI); // 3.14159
console.log(circleArea(5)); // 78.5...
// تغییر نام — برای تداخل:
import { PI as PI_NUMBER } from "./utils.js";
// همه با یک نام:
import * as Utils from "./utils.js";
console.log(Utils.PI);
console.log(Utils.circleArea(5));
Default Export — خروجی پیشفرض
// User.js — فقط یکی default:
export default class User {
constructor(name) { this.name = name; }
}
// import — هر نامی میخواهی:
import User from "./User.js";
import MyUser from "./User.js"; // همان چیز!
// ترکیب default و named:
export default User;
export const VERSION = "1.0";
// import هر دو:
import User, { VERSION } from "./User.js";
Default برای چیز اصلی فایل (کلاس/کامپوننت)، Named برای ابزارها.
Re-Export — صادرکردن مجدد
// index.js — نقطه ورود:
export { default as User } from "./User.js";
export { default as Product } from "./Product.js";
export * from "./utils.js"; // همه ابزارها
// حالا از یکجا:
import { User, Product, PI } from "./index.js";
Dynamic Import — بارگذاری پویا
// import() — Promise برمیگرداند:
const module = await import("./heavy-chart.js");
module.renderChart(data);
// شرطی:
if (userNeedsCharts) {
const { Chart } = await import("./chart.js");
new Chart(element, data);
}
// با then:
import("./analytics.js")
.then(module => module.trackPageView())
.catch(err => console.log("لود نشد"));
// Code Splitting — فقط وقتی لازم است لود میشود!
Module Scope و Hoisting
// counter.js:
let count = 0; // خصوصی — خارج از فایل دیده نمیشود
export function increment() {
return ++count; // دسترسی داخل فایل OK
}
// app.js:
import { increment } from "./counter.js";
increment();
increment();
// count مستقیم قابل دسترسی نیست! ✓
ماژولها Singleton هستند
// config.js:
console.log("اجرا شد — فقط بار اول!");
export const config = { api: "/api" };
// a.js: import { config } from "./config.js";
// b.js: import { config } from "./config.js";
// → "اجرا شد" فقط یکبار چاپ میشود
// → config در هر دو فایل همان شیء است
import.meta — اطلاعات ماژول
// در ES Module:
console.log(import.meta.url); // آدرس کامل فایل
// Dynamic import نسبی:
const helpers = await import(new URL("./helpers.js", import.meta.url));
CommonJS — استاندارد Node.js
// utils.js — CJS:
const PI = 3.14159;
function circleArea(r) { return PI * r ** 2; }
// export — module.exports:
module.exports = { PI, circleArea };
// import:
const { PI, circleArea } = require("./utils");
// یا همه:
const utils = require("./utils");
utils.circleArea(5);
ESM در Node.js
// package.json:
// { "type": "module" }
// حالا import کار میکند:
import fs from "node:fs";
import path from "node:path";
// یا پسوند .mjs:
// script.mjs — بدون تغییر package.json
مقایسه ESM و CommonJS
| ویژگی | ES Modules | CommonJS |
|---|---|---|
| سینتکس | import/export | require/module.exports |
| بارگذاری | Async — میشود موازی | Sync — ترتیبی |
| Tree Shaking | پشتیبانی ✓ | نه |
| مرورگر | بومی ✓ | نیاز به Bundler |
| Dynamic | import() | require شرطی |
| مقدار | Live Binding | کپی هنگام require |
مدیریت وابستگیها با npm
// package.json:
{
"name": "my-app",
"type": "module",
"dependencies": {
"lodash": "^4.17.21"
}
}
// نصب:
// npm install lodash
// استفاده:
import _ from "lodash";
_.chunk([1, 2, 3, 4], 2); // [[1,2],[3,4]]
ساختار پروژه ماژولار
src/
index.js — نقطه شروع
utils/
format.js — ابزار قالببندی
validate.js — اعتبارسنجی
index.js — re-export همه
services/
api.js — ارتباط سرور
auth.js — احراز هویت
models/
User.js
Product.js
// index.js:
import { formatDate } from "./utils/index.js";
import ApiService from "./services/api.js";
Top-Level await
// در ماژول — بدون wrapper:
const config = await fetch("/config.json").then(r => r.json());
// همه importها بعد از این منتظر میمانند:
export const API_URL = config.apiUrl;
// سایر فایلها:
import { API_URL } from "./config.js"; // config لود شده
جمعبندی
| کار | سینتکس |
|---|---|
| خروجی نامدار | export const x |
| خروجی پیشفرض | export default x |
| ورود نامدار | import { x } |
| ورود همه | import * as ns |
| پویا | import() — Promise |
این مبحث بخشی از دوره آموزش کامل جاوا اسکریپت است.