الوحدات في JavaScript: import و export
كل برامجك حتى الآن كانت في ملف واحد. هذا مناسب لخمسين سطراً، لكن المشاريع الحقيقية تصل إلى آلاف الأسطر، وملف واحد بهذا الحجم يصعب أن تجد فيه شيئاً. الحل هو الوحدات (Modules): تقسّم الكود إلى ملفات صغيرة، كل ملف مسؤول عن شيء واحد، ويأخذ من الملفات الأخرى ما يحتاجه فقط.
ما هي الوحدة؟
Section titled “ما هي الوحدة؟”الوحدة ملف JavaScript عادي، له ميزتان:
- ما بداخله خاص به. المتغيرات والدوال لا تتسرب إلى الملفات الأخرى، فلا يتصادم اسمان متشابهان في ملفين.
- يختار ما يصدّره (export) للآخرين، وما يستورده (import) منهم.
تخيّل مطبخاً منظماً: درج للسكاكين، ودرج للملاعق، ورف للتوابل. عندما تطبخ تفتح الدرج الذي تحتاجه وتأخذ منه الأداة المطلوبة فقط. ولو رُميت كل الأدوات في صندوق واحد لضاع وقتك في البحث.
التصدير: export
Section titled “التصدير: export”ضع كلمة export قبل أي دالة أو متغير تريد أن تراه الملفات الأخرى:
export const PI = 3.14159;
export function add(a, b) { return a + b;}
export function circleArea(radius) { return roundTwo(PI * radius * radius);}
function roundTwo(number) { return Math.round(number * 100) / 100;}الدالة roundTwo بلا export، فهي أداة داخلية لا يراها أحد خارج هذا الملف.
الاستيراد: import
Section titled “الاستيراد: import”في ملف آخر، اطلب ما تحتاجه بالاسم بين قوسين معقوفين:
import { add, circleArea } from "./math.js";
console.log(add(2, 3));console.log(circleArea(10));5314.16- الأسماء بين القوسين يجب أن تطابق الأسماء المصدَّرة تماماً.
- المسار يبدأ بـ
./ومعناها «في المجلد نفسه»، وينتهي بامتداد الملف.js. - أسطر
importتُكتب في أعلى الملف.
ولو حاولت استيراد roundTwo لظهر خطأ، لأن الملف لم يصدّرها.
ربط الوحدة بالصفحة
Section titled “ربط الوحدة بالصفحة”في HTML أضف type="module" إلى وسم script، واربط الملف الرئيسي فقط:
<script type="module" src="main.js"></script>المتصفح يقرأ أسطر import في main.js ويحمّل باقي الملفات بنفسه. ووسم الوحدة مؤجَّل تلقائياً كأنك كتبت defer، فيُنفَّذ بعد أن تجهز عناصر الصفحة.
إعادة التسمية واستيراد الكل
Section titled “إعادة التسمية واستيراد الكل”إذا تعارض اسم مستورد مع اسم عندك، غيّره بكلمة as:
import { add as sum } from "./math.js";
console.log(sum(10, 5));15ويمكنك أن تستورد كل ما يصدّره الملف في كائن واحد:
import * as math from "./math.js";
console.log(math.PI);console.log(math.add(1, 2));3.141593التصدير الافتراضي: default
Section titled “التصدير الافتراضي: default”إذا كان الملف يقدّم شيئاً رئيسياً واحداً، يمكنه أن يصدّره كتصدير افتراضي:
export default function greet(name) { return `أهلاً يا ${name}`;}وعند الاستيراد تكتب الاسم بدون قوسين معقوفين، وتختار له أي اسم تريده:
import greet from "./greet.js";
console.log(greet("مريم"));أهلاً يا مريم| التصدير بالاسم | التصدير الافتراضي | |
|---|---|---|
| الكتابة | export function add |
export default function greet |
| الاستيراد | import { add } بقوسين |
import greet بدون قوسين |
| العدد في الملف | أي عدد | واحد فقط |
مثال كامل: سلة مشتريات في ثلاثة ملفات
Section titled “مثال كامل: سلة مشتريات في ثلاثة ملفات”shop/├─ index.html├─ main.js├─ cart.js└─ format.jsملف صغير لتنسيق الأسعار:
export function formatPrice(amount) { return `${amount.toFixed(2)} جنيه`;}وملف السلة يستورد منه، ويصدّر دواله:
import { formatPrice } from "./format.js";
const items = [];
export function addItem(name, price) { items.push({ name, price });}
export function getCount() { return items.length;}
export function getTotal() { const total = items.reduce((sum, item) => sum + item.price, 0); return formatPrice(total);}والملف الرئيسي يستخدم السلة:
import { addItem, getCount, getTotal } from "./cart.js";
addItem("قلم", 15);addItem("دفتر", 40.5);
console.log("عدد المنتجات:", getCount());console.log("الإجمالي:", getTotal());عدد المنتجات: 2الإجمالي: 55.50 جنيهلاحظ أن المصفوفة items بلا export. الملف الرئيسي لا يستطيع أن يلمسها مباشرة، ولا يغيّرها إلا عبر الدوال التي سمحنا بها. وهذه نفس فكرة الخصائص الخاصة في درس الكلاسات، لكن على مستوى الملف.
ولاحظ أيضاً أن main.js لا يعرف شيئاً عن format.js. كل ملف يستورد ما يحتاجه هو فقط.
جرّب بنفسك
Section titled “جرّب بنفسك”هذا الدرس يحتاج عدة ملفات، فطبّقه على جهازك:
- أنشئ مجلداً باسم
shopوفيه الملفات الثلاثة السابقة. - أضف ملف
index.htmlفيه السطر<script type="module" src="main.js"></script>. - شغّل الصفحة بـ Live Server وافتح Console. يجب أن ترى:
عدد المنتجات: 2الإجمالي: 55.50 جنيه- أضف إلى
cart.jsدالةremoveItem(name)وصدّرها، ثم استوردها فيmain.jsواحذف القلم. يجب أن يصبح الإجمالي40.50 جنيه.
أخطاء شائعة
Section titled “أخطاء شائعة”- نسيان
type="module": يظهر الخطأCannot use import statement outside a module. - نسيان
./أو الامتداد: كتابة"math"أو"./math"لا تعمل في المتصفح. اكتب المسار كاملاً:"./math.js". - الخلط بين النوعين: استيراد تصدير افتراضي بقوسين، أو تصدير بالاسم بدون قوسين. راجع طريقة التصدير في الملف الآخر.
- فتح الصفحة بالنقر المزدوج: الوحدات لا تُحمَّل بدون خادم محلي.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
في الملف tools.js كتبنا export function sayHi(). ما سطر الاستيراد الصحيح؟
التصدير بالاسم يُستورد بين قوسين معقوفين، والمسار يُكتب كاملاً مع ./ والامتداد.
سؤال
دالة داخل وحدة لم نكتب قبلها export. من يستطيع استدعاءها؟
كل ما في الوحدة خاص بها ما لم يُصدَّر، وهذا يحمي الأدوات الداخلية ويمنع تصادم الأسماء.
الخلاصة
Section titled “الخلاصة”- الوحدة ملف له نطاقه الخاص، يصدّر ما يريد ويستورد ما يحتاج.
exportقبل الدالة أو المتغير، وimport { الاسم } from "./file.js"لاستيراده.export defaultلشيء رئيسي واحد، ويُستورد بدون قوسين معقوفين.- اربط الملف الرئيسي بـ
<script type="module">، وشغّل الصفحة من خادم محلي. - قسّم مشروعك إلى ملفات صغيرة، كل ملف له مسؤولية واحدة واضحة.