التفكيك والنشر في JavaScript: Destructuring و Spread
افتح أي كود JavaScript حديث وستجد أقواساً معقوفة على يسار علامة =، وثلاث نقاط ... في كل مكان. هاتان هما التفكيك (Destructuring) والنشر (Spread)، وهما من أكثر مزايا اللغة الحديثة استخداماً. لا يضيفان قدرة جديدة، لكنهما يجعلان الكود أقصر وأوضح بكثير. وفهمهما شرط لقراءة أي مشروع حقيقي.
تفكيك الكائنات
Section titled “تفكيك الكائنات”رأيت لمحة منه في درس الكائنات. بدلاً من هذا:
const user = { name: "سارة", age: 14, city: "طنطا" };
const userName = user.name;const userAge = user.age;نكتب سطراً واحداً:
const { name, age } = user;console.log(name, age);سارة 14الأقواس المعقوفة على يسار علامة = معناها: «أخرج من الكائن الخاصيتين name و age، وضعهما في متغيرين بنفس الاسم».
تخيّل التفكيك مثل فتح حقيبة السفر: بدلاً من أن تمد يدك إلى الحقيبة كل مرة، تخرج ما تحتاجه مرة واحدة وتضعه على الطاولة.
تغيير الاسم والقيمة الافتراضية
Section titled “تغيير الاسم والقيمة الافتراضية”const { city: town, country = "مصر" } = user;console.log(town);console.log(country);طنطامصرcity: town: خذ الخاصيةcityوضعها في متغير اسمهtown.country = "مصر": إذا لم تكن الخاصية موجودة في الكائن فاستخدم هذه القيمة.
التفكيك في معاملات الدالة
Section titled “التفكيك في معاملات الدالة”هذا أكثر استخدام ستراه. بدلاً من أن تستقبل الدالة كائناً ثم تكتب options.title و options.size في كل مكان:
function showProduct({ title, price, currency = "جنيه" }) { console.log(`${title}: ${price} ${currency}`);}
showProduct({ title: "كتاب", price: 80 });showProduct({ price: 15, title: "قلم", currency: "ريال" });كتاب: 80 جنيهقلم: 15 ريالفائدة مهمة: ترتيب القيم عند الاستدعاء لم يعد مهماً، لأن كل قيمة لها اسمها. وهذا أوضح كثيراً من دالة تأخذ خمسة معاملات لا تتذكر ترتيبها.
تفكيك المصفوفات
Section titled “تفكيك المصفوفات”مع المصفوفات نستخدم الأقواس المربعة، والتوزيع يكون بالترتيب لا بالاسم:
const colors = ["أحمر", "أخضر", "أزرق"];const [first, second] = colors;console.log(first, second);
const [, , third] = colors;console.log(third);أحمر أخضرأزرقالفاصلة الفارغة تتخطى عنصراً. ومن الحيل اللطيفة تبديل قيمتي متغيرين بدون متغير ثالث:
let a = 1;let b = 2;[a, b] = [b, a];console.log(a, b);2 1النشر: النقاط الثلاث
Section titled “النشر: النقاط الثلاث”معامل النشر ... يفك محتويات مصفوفة أو كائن، كأنك كتبت عناصرها واحداً واحداً.
تخيّله مثل إفراغ علبة أقلام على المكتب: كانت الأقلام شيئاً واحداً داخل العلبة، وصارت قطعاً منفصلة.
نسخ المصفوفات ودمجها
Section titled “نسخ المصفوفات ودمجها”const morning = ["فطور", "مذاكرة"];const evening = ["رياضة", "قراءة"];
const day = [...morning, "غداء", ...evening];console.log(day);
const copy = [...morning];copy.push("نوم");console.log(morning.length, copy.length);[ 'فطور', 'مذاكرة', 'غداء', 'رياضة', 'قراءة' ]2 3لاحظ أن الإضافة إلى copy لم تغيّر morning، لأن [...morning] أنشأت مصفوفة جديدة.
نسخ الكائنات وتعديلها
Section titled “نسخ الكائنات وتعديلها”const settings = { theme: "light", fontSize: 16 };const updated = { ...settings, theme: "dark" };
console.log(updated);console.log(settings.theme);{ theme: 'dark', fontSize: 16 }light{ ...settings, theme: "dark" } معناها: «انسخ كل خصائص settings، ثم اجعل theme تساوي dark». الخاصية المكتوبة لاحقاً تغلب السابقة. والكائن الأصلي لم يتغير.
هذا النمط، أي إنشاء نسخة معدّلة بدلاً من تعديل الأصل، هو أساس العمل في مكتبات الواجهات الحديثة مثل React.
نشر مصفوفة كمعاملات دالة
Section titled “نشر مصفوفة كمعاملات دالة”const grades = [70, 95, 82];console.log(Math.max(...grades));95Math.max تنتظر أرقاماً منفصلة لا مصفوفة، والنشر يفك المصفوفة إلى معاملات.
معامل rest: الباقي
Section titled “معامل rest: الباقي”نفس النقاط الثلاث، لكن بمعنى معاكس. إذا جاءت على يسار علامة = أو في تعريف دالة، فهي تجمع ما بقي:
const [winner, ...others] = ["منى", "عمر", "هدى", "علي"];console.log(winner);console.log(others);
const { theme, ...rest } = { theme: "dark", fontSize: 16, lang: "ar" };console.log(rest);منى[ 'عمر', 'هدى', 'علي' ]{ fontSize: 16, lang: 'ar' }وفي الدوال تجمع أي عدد من المعاملات في مصفوفة:
function sum(...numbers) { return numbers.reduce((total, n) => total + n, 0);}
console.log(sum(1, 2));console.log(sum(5, 10, 15, 20));350| النشر (Spread) | الباقي (Rest) | |
|---|---|---|
| ماذا يفعل | يفك مجموعة إلى عناصر | يجمع عناصر في مجموعة |
| أين يُكتب | عند إنشاء مصفوفة أو كائن، أو استدعاء دالة | عند التفكيك، أو في تعريف الدالة |
جرّب بنفسك
Section titled “جرّب بنفسك”الناتج
جرّب أن تضيف خاصية color إلى discounted، ثم اطبع firstItem وتأكد أنه لم يتغير.
أخطاء شائعة
Section titled “أخطاء شائعة”- تفكيك خاصية غير موجودة بدون قيمة افتراضية: تحصل على
undefinedبهدوء. أضف قيمة افتراضية إذا كانت الخاصية اختيارية. - الظن أن النشر ينسخ نسخاً عميقاً: النشر ينسخ المستوى الأول فقط. إذا كان داخل الكائن كائن آخر، فالنسخة والأصل يتشاركانه.
- نسيان ترتيب النشر في الكائنات:
{ theme: "dark", ...settings }تجعل قيمةsettingsهي الغالبة، وهو عكس ما تريد غالباً.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
ما قيمة x بعد السطر: const { x = 5 } = { y: 2 }; ؟
الخاصية x غير موجودة في الكائن، فتُستخدم القيمة الافتراضية 5.
سؤال
كيف تنشئ نسخة مستقلة من مصفوفة arr؟
النشر داخل مصفوفة جديدة ينشئ نسخة مستقلة. أما المساواة المباشرة فتجعل المتغيرين يشيران إلى نفس المصفوفة.
الخلاصة
Section titled “الخلاصة”- التفكيك يستخرج قيماً من كائن بالاسم، ومن مصفوفة بالترتيب.
- يمكن تغيير الاسم بـ
:وتحديد قيمة افتراضية بـ=. - التفكيك في معاملات الدالة يجعل الاستدعاء أوضح ولا يعتمد على الترتيب.
- النشر
...ينسخ ويدمج المصفوفات والكائنات بدون تعديل الأصل. - معامل rest يجمع الباقي في مصفوفة أو كائن.