Menu
العربية

مصفوفات JavaScript: الإنشاء والتعديل والتكرار

كيف تعمل المصفوفات في JavaScript: إنشاؤها، الوصول للعناصر، الطول، push وpop، الفرق بين slice وsplice، وأفضل طرق التكرار عليها.

المصفوفة قائمة مرتّبة من القيم

مصفوفات javascript هي عبارة عن تسلسل مرتّب من القيم. هذه القيم يمكن أن تكون من أي نوع — أرقام، نصوص، كائنات، وحتى مصفوفات أخرى — وليس بالضرورة أن تكون كلها من نفس النوع. تُنشئ المصفوفة باستخدام الأقواس المربّعة:

index.js
Output
Click Run to see the output here.

صيغة المصفوفة الحرفية هذه هي ما ستستخدمه في 99% من الحالات لإنشاء المصفوفات. هناك أيضًا new Array(...)، لكن انتبه لفخ مهم فيه: new Array(3) ينشئ مصفوفة بطول 3 بدون أي عناصر فعلية، وليس [3]. التزم باستخدام [].

الفهرسة تبدأ من الصفر

تصل إلى عناصر المصفوفة عبر موقعها، والعدّ يبدأ من 0:

index.js
Output
Click Run to see the output here.

ملاحظتان مهمتان هنا. الأولى أن الوصول إلى عنصر خارج حدود المصفوفة لا يُطلق أي خطأ، بل يُعيد ببساطة undefined، وهذا من أكثر الأسباب شيوعًا وراء سؤال "لماذا القيمة undefined؟". الثانية أنه بإمكانك إسناد قيمة إلى أي فهرس تريده، حتى لو كان بعد نهاية المصفوفة، وسيقوم JavaScript بتمديد المصفوفة دون أي اعتراض:

index.js
Output
Click Run to see the output here.

تتحول الخانتان 3 و4 إلى "فراغات" (ثقوب مبعثرة)، ويقفز length إلى 6. نادرًا ما تحتاج هذا السلوك فعلًا، فهو أثر جانبي لمرونة المصفوفات المفرطة في JavaScript، لا ميزة يُعتمد عليها.

خاصية length تتحدث تلقائيًا

قيمة array.length تساوي دائمًا أعلى فهرس في المصفوفة زائد واحد، وتتحدث ذاتيًا عند إضافة أي عنصر أو حذفه:

index.js
Output
Click Run to see the output here.

تستحق هذه الحيلة الأخيرة أن تبقى في ذاكرتك: إسناد قيمة إلى length يقصّ المصفوفة. فكتابة nums.length = 0 طريقة سريعة لتفريغها في مكانها.

الدوال push و pop و shift و unshift

أربع دوال للإضافة والحذف من طرفي المصفوفة:

index.js
Output
Click Run to see the output here.
  • push(x) يُضيف عنصرًا في نهاية المصفوفة ويُعيد الطول الجديد.
  • pop() يحذف آخر عنصر ويُعيده.
  • unshift(x) يُضيف عنصرًا في بداية المصفوفة.
  • shift() يحذف أول عنصر.

الدالتان push و pop سريعتان، أما shift و unshift فتضطران لإعادة ترتيب فهارس بقية العناصر، لذا تصبحان أبطأ مع المصفوفات الكبيرة. لا مشكلة مع الأحجام المعتادة في الاستخدام اليومي، لكن من المفيد الانتباه لهذا الأمر لو كنت تتعامل مع ملايين العناصر.

الفرق بين slice و splice في javascript

اسم الدالتين متشابه لكن سلوكهما مختلف تمامًا. إذا فهمت الفرق بينهما جيدًا، ستوفّر على نفسك الكثير من الحيرة لاحقًا.

الدالة slice(start, end) تُعيد نسخة من جزء من المصفوفة دون المساس بالأصل. والقيمة end غير مشمولة في النتيجة:

index.js
Output
Click Run to see the output here.

splice(start, deleteCount, ...items) تُعدِّل المصفوفة الأصلية نفسها، وتستطيع حذف عناصر أو إدراج عناصر جديدة أو الاثنين معًا، ثم تُعيد ما حُذف منها:

index.js
Output
Click Run to see the output here.

قاعدة بسيطة تساعدك على التمييز: لو جاء في بالك أنك «تقتطع» شريحة من رغيف خبز، فهذه slice. أما لو خطر لك أنك «توصل» شريطًا سينمائيًا (تقص وتُدخل)، فهذه splice.

البحث داخل المصفوفة: indexOf و includes و find

هناك ثلاث طرق للبحث عن عنصر داخل مصفوفة javascript، وكل واحدة تناسب موقفًا مختلفًا:

index.js
Output
Click Run to see the output here.
  • indexOf(x) يرجّع لك موقع العنصر، أو -1 لو مش موجود. مناسب لما تحتاج تعرف الفهرس نفسه.
  • includes(x) يرجّع قيمة منطقية (true/false). أنظف لما يكون كل اللي يهمك هو: "هل العنصر موجود أصلاً؟" كمان يتعامل مع NaN بشكل صحيح، عكس indexOf.
  • find(predicate) يمرّر دالة على كل عنصر ويرجّع أول عنصر يحقّق الشرط. هذه هي الدالة المناسبة لما تشتغل على مصفوفة كائنات javascript، لأن indexOf و includes يعتمدان على المقارنة الصارمة فقط.

التكرار على مصفوفة javascript

في أكثر من طريقة جيدة، وكل وحدة تناسب موقف مختلف:

index.js
Output
Click Run to see the output here.

for...of هو الخيار المبدئي عند التكرار على مصفوفة javascript — واضح، يشتغل مع أي كائن قابل للتكرار، ويعطيك القيمة مباشرة. أما forEach فمناسب لما تحتاج الفهرس (الـ index) معاها ومش ناوي تخرج من الحلقة في النص، لأنك ما تقدر تستخدم break جواها. وحلقة for الكلاسيكية بالفهرس أطول في الكتابة بس تعطيك تحكّم كامل — استخدمها لما تحتاج تتجاوز عناصر معينة، أو تمشي من الآخر للأول، أو الاثنين سوا.

في حلقة وحدة يُفضَّل تتجنبها: for...in. هذه تمرّ على المفاتيح وتشمل حتى الخصائص الموروثة، وهي مخصّصة للكائنات لا للمصفوفات.

نسخ المصفوفات ودمجها

المصفوفات في javascript قيم مرجعية (reference values)، يعني لما تسند مصفوفة لمتغير ثاني فأنت ما نسخت شي — صار عندك اسمان يشيران لنفس المصفوفة:

index.js
Output
Click Run to see the output here.

للنسخ الفعلي، استخدم معامل الانتشار (spread operator) أو slice():

index.js
Output
Click Run to see the output here.

كلا الطريقتين تعطيك نسخة سطحية (shallow copy) — يعني المصفوفة الخارجية جديدة، لكن لو كانت العناصر كائنات، فهذه الكائنات لا تزال مشتركة بين النسختين. كما أن عامل النشر (spread) هو أنظف أسلوب لدمج أكثر من مصفوفة:

index.js
Output
Click Run to see the output here.

مصفوفة كائنات في javascript

في الكود الحقيقي، غالبية المصفوفات اللي بتشتغل عليها بتكون مصفوفة كائنات. نفس الدوال اللي اتكلمنا عنها بتشتغل عادي، بس عملية المطابقة بتبقى أكتر إثارة:

index.js
Output
Click Run to see the output here.

filter تُرجع مصفوفة جديدة تحتوي على العناصر التي تُحقّق شرطًا معيّنًا، بينما map تُرجع مصفوفة جديدة بعد تطبيق تحويل على كل عنصر. الجمع بين الاثنتين هو الأسلوب المعتاد للتعامل مع مصفوفة كائنات javascript، وسنتعمّق أكثر في هذه العائلة من الدوال في الصفحة التالية.

المصفوفات مقابل الكائنات

إليك طريقة بسيطة للتفكير في الأمر: استخدم المصفوفة حين يكون الترتيب مهمًّا وتتعامل مع قائمة من عناصر من النوع نفسه، واستخدم الكائن (أو Map) حين تريد الوصول إلى القيم عبر مفاتيح بأسماء. "الأول، الثاني، الثالث" مجال المصفوفات، أمّا "أعطني المستخدم صاحب المعرّف 42" فهو مجال الكائنات أو Map.

طبعًا يمكن الدمج بينهما — فمصفوفات الكائنات منتشرة في كل مكان — لكن لا تستعمل المصفوفة كقاموس مفاتيح، ولا تستعمل الكائن كقائمة مرتّبة. كلٌّ منهما يُتقن مهمّته الخاصّة.

التالي: التفكيك (Destructuring)

استخراج القيم من المصفوفات عبر الفهرس (والخصائص من الكائنات عبر الاسم) عمليّة متكرّرة لدرجة أنّ JavaScript خصّصت لها صياغة مستقلّة. هذه الصياغة تُسمّى التفكيك (Destructuring)، وهي موضوع الصفحة القادمة.

الأسئلة الشائعة

كيف تُنشئ مصفوفة في JavaScript؟

الطريقة الشائعة والأنظف هي استخدام الأقواس المربعة مباشرة: const fruits = ['apple', 'banana']. أما الـ constructor new Array(3) فموجود لكنه نادراً ما يكون ما تحتاجه فعلاً، لأنه ينشئ مصفوفة بطول 3 بدون عناصر حقيقية، وهذا سلوك مربك للكثيرين.

كيف أحذف عنصراً من مصفوفة في JavaScript؟

لحذف آخر عنصر استخدم pop()، وللعنصر الأول استخدم shift(). أما الحذف من أي موضع في المنتصف، فاستخدم splice(index, 1) لتعديل المصفوفة نفسها، أو filter(...) إذا كنت تريد مصفوفة جديدة بدون العنصر. انتبه: splice يُعدّل المصفوفة الأصلية، بينما filter لا يفعل.

ما الفرق بين slice وsplice؟

slice(start, end) يُرجع نسخة سطحية من جزء من المصفوفة ولا يمس الأصلية. بينما splice(start, deleteCount, ...items) يُعدّل المصفوفة الأصلية: يحذف عناصر، ويُدرج أخرى إن رغبت، ويُرجع العناصر المحذوفة. حرف واحد يفرق، لكن السلوك مختلف تماماً.

كيف أتحقق من وجود قيمة داخل مصفوفة JavaScript؟

استخدم array.includes(value) ويُرجع true أو false، ويتعامل مع NaN بشكل صحيح. أما indexOf(value) فيُرجع موقع العنصر أو -1 إذا لم يجده، وهو مفيد حين تحتاج الفهرس نفسه. وإذا كان البحث معقداً (مثلاً داخل كائنات)، استخدم some(predicate) أو find(predicate).

تعلّم البرمجة مع Coddy

ابدأ الآن