| العامل | السياق | الوظيفة |
|---|---|---|
| Spread | عند إنشاء مصفوفة/كائن/تمرير وسائط | توزيع عناصر موجودة |
| Rest | عند تعريف معاملات/تفكيك | تجميع عناصر متفرقة |
عامل التوزيع (Spread Operator) وعامل الجمع (Rest Operator) يستخدمان نفس الرمز البصري بالضبط (ثلاث نقاط ...)، لكن معناهما يختلف تماماً حسب السياق الذي يظهران فيه — وهذا مصدر خلط شائع للمبتدئين رغم أن التمييز بينهما بسيط بمجرد فهمه.
عامل التوزيع (Spread) يُستخدم "لتفكيك" أو "توزيع" عناصر مصفوفة أو خصائص كائن إلى عناصر أو خصائص منفصلة، ويظهر عادة عند إنشاء قيمة جديدة: داخل مصفوفة جديدة []، أو كائن جديد {}، أو عند تمرير وسائط لدالة. استخدامه الأكثر شيوعاً هو نسخ مصفوفات أو كائنات بشكل سطحي (Shallow Copy) دون تعديل الأصل، ودمج عدة مصفوفات أو كائنات في واحدة جديدة بسهولة.
عامل الجمع (Rest) يُستخدم على العكس تماماً — "لتجميع" عدة عناصر متفرقة في مصفوفة واحدة، ويظهر فقط في سياق "الاستقبال": عند تعريف معاملات دالة (كما تعلمنا في موضوع المعاملات)، أو عند تفكيك مصفوفة أو كائن حيث تريد تجميع "البقية" من العناصر أو الخصائص غير المذكورة صراحة في متغير واحد.
القاعدة الذهبية للتمييز بينهما بسهولة: إذا ظهرت ... عند "إنشاء" قيمة جديدة (توزيع)، فهي Spread. وإذا ظهرت عند "استقبال" قيم (تجميع)، فهي Rest. من المهم أيضاً معرفة أن كلا العاملين يقومان بنسخ سطحي فقط (Shallow) وليس عميقاً (Deep) — أي أن الكائنات أو المصفوفات المتداخلة بداخل القيمة المنسوخة تبقى مُشارَكة بالمرجع مع الأصل.
| 1 | // Spread: توزيع عند الإنشاء |
| 2 | const أ = [1, 2, 3]; |
| 3 | const ب = [...أ, 4, 5]; // [1, 2, 3, 4, 5] |
| 4 | const كائن_جديد = { ...{ س: 1 }, ص: 2 }; // { س: 1, ص: 2 } |
| 5 | |
| 6 | // Rest: تجميع عند الاستقبال |
| 7 | function جمع(...أرقام) { |
| 8 | return أرقام.reduce((م, ر) => م + ر, 0); |
| 9 | } |
| 10 | const [أول, ...الباقي] = [1, 2, 3, 4]; // أول=1, الباقي=[2,3,4] |
مثال 1: دمج مصفوفات وكائنات بعامل التوزيع
| 1 | // دمج مصفوفات وكائنات بعامل التوزيع |
| 2 | const فواكه1 = ["تفاح", "موز"]; |
| 3 | const فواكه2 = ["عنب", "مانجو"]; |
| 4 | const كل_الفواكه = [...فواكه1, ...فواكه2]; |
| 5 | console.log(كل_الفواكه); // ["تفاح", "موز", "عنب", "مانجو"] |
| 6 | |
| 7 | const افتراضي = { لون: "أبيض", حجم: "M" }; |
| 8 | const مخصص = { ...افتراضي, لون: "أسود" }; // الخصائص المكررة: الأحدث تفوز |
| 9 | console.log(مخصص); // { لون: "أسود", حجم: "M" } |
مثال 2: استخدام Rest لاستخراج خصائص واستبعاد أخرى
| 1 | // Rest في تفكيك الكائنات لاستخراج البقية |
| 2 | const منتج = { id: 1, اسم: "لابتوب", سعر: 3000, مخزون: 5 }; |
| 3 | const { id, ...بيانات_العرض } = منتج; |
| 4 | console.log(بيانات_العرض); // { اسم: "لابتوب", سعر: 3000, مخزون: 5 } بدون id |
| 5 | |
| 6 | // مفيد لإزالة حقل حساس مثل كلمة مرور قبل إرسال البيانات للواجهة |
| 7 | const مستخدم = { اسم: "سارة", كلمة_المرور: "12345", بريد: "s@e.com" }; |
| 8 | const { كلمة_المرور, ...مستخدم_آمن } = مستخدم; |
| 9 | console.log(مستخدم_آمن); // بدون كلمة المرور |