إدراج عنصر في مصفوفة حسب الفهرس: كيف يعمل تحت الغطاء في JS

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا سؤال إدراج عنصر في مصفوفة شائع جدًا؟

\n

تخيل: أنت تكتب كودًا، وتحتاج إلى إضافة مهمة جديدة في منتصف قائمة المهام، أو إدراج مستخدم في مصفوفة مرتبة أبجديًا. قد يبدو الأمر بسيطًا؟ لكن إذا كنت مبتدئًا في JavaScript، فإن أول فكرة تتبادر إلى ذهنك هي استخدام push() أو unshift(). ومع ذلك، فهما يضيفان العنصر فقط في النهاية أو البداية. ولكن ماذا لو كنت بحاجة إلى فهرس محدد؟

\n

هذا السؤال بالتحديد حصد آلاف المشاهدات على Stack Overflow. في هذه المقالة، لن نقدم لك الإجابة الجاهزة فحسب، بل سننظر تحت غطاء محرك JavaScript ونحلل كيف يعمل إدراج العنصر في المصفوفة فعليًا. ستتعلم ليس فقط سحر طريقة splice()، بل ستفهم أيضًا العمليات التي تحدث في الذاكرة. هيا بنا!

\n\n

الإجابة المباشرة: كيفية إدراج عنصر حسب الفهرس

\n

أبسط وأصح طريقة هي استخدام طريقة splice(). هذه الطريقة تغير محتوى المصفوفة عن طريق حذف أو استبدال أو إضافة عناصر. إليك كيف تبدو الإدراج الكلاسيكي:

\n\n
let fruits = ['apple', 'banana', 'cherry'];\nlet index = 1; // الإدراج بعد 'apple'\nlet itemToInsert = 'orange';\n\nfruits.splice(index, 0, itemToInsert);\nconsole.log(fruits); // ['apple', 'orange', 'banana', 'cherry']
\n\n

دعنا نحلل الصيغة:

\n
    \n
  • الوسيطة الأولى (index) — الفهرس الذي نبدأ منه بتغيير المصفوفة.
  • \n
  • الوسيطة الثانية (0) — عدد العناصر المراد حذفها. الصفر يعني أننا لا نحذف شيئًا، بل نقوم فقط بالإدراج.
  • \n
  • الوسيطة الثالثة وما بعدها — العناصر التي نريد إضافتها. يمكن تمرير عدة قيم.
  • \n
\n\n

هذه الطريقة هي سكين سويسري متعدد الاستخدامات للتعامل مع المصفوفات. ولكن كيف تعمل داخليًا؟ دعنا نكتشف ذلك.

\n\n

تحت الغطاء: كيف يقوم splice() بتحريك العناصر

\n

عند استدعاء splice()، يقوم محرك JavaScript (مثل V8 في Chrome أو SpiderMonkey في Firefox) بتنفيذ عدة خطوات:

\n\n

1. التحقق من الحدود والنوع

\n

يتحقق المحرك مما إذا كان الفهرس رقمًا وما إذا كان ضمن طول المصفوفة. إذا كان الفهرس سالبًا، يتم تحويله إلى length + index. إذا قمت بتمرير قيمة غير رقمية، يتم تحويلها إلى رقم (غالبًا إلى 0 أو NaN).

\n\n

2. إنشاء "فجوة" في المصفوفة

\n

لنفترض أن لدينا مصفوفة [A, B, C]، ونقوم بإدراج X في الموضع 1. يجب على المحرك تحرير مساحة. إنه لا يقوم فقط "بكتابة" X فوق B. بدلاً من ذلك، يقوم بإزاحة جميع العناصر، بدءًا من الفهرس 1، بمقدار موضع واحد إلى اليمين. أي أن B يصبح في مكان C، و C في موضع جديد (الفهرس 3). يُسمى هذا الإزاحة.

\n\n

3. التحسين: المصفوفة المستمرة مقابل المصفوفة المتناثرة

\n

مصفوفات JavaScript ليست مجرد سلسلة من خلايا الذاكرة، كما في C. إنها كائنات ذات سلوك خاص. يحاول المحرك تخزين البيانات في مخزن مؤقت مستمر (كما في المصفوفات النمطية). إذا تم إدراج عناصر في المنتصف، يضطر المحرك إلى إعادة توزيع الذاكرة: تخصيص كتلة جديدة بحجم أكبر ونسخ جميع العناصر إليها. هذه عملية O(n) (تعقيد خطي). كلما كانت المصفوفة أكبر، كلما استغرق الإدراج وقتًا أطول.

\n\n

إذا كانت المصفوفة متناثرة (sparse)، أي تحتوي على "فجوات" (مثل [1, , 3])، يتحول المحرك إلى التخزين على شكل جدول تجزئة. قد يكون الإدراج في مثل هذه المصفوفة أسرع، لكنه يستهلك ذاكرة أكبر.

\n\n

4. تحديث الطول

\n

بعد الإزاحة والإدراج، يقوم المحرك بتحديث خاصية length للمصفوفة. إذا قمت بإدراج عنصر واحد، سيزيد الطول بمقدار 1.

\n\n

إليك تصور مبسط للعملية:

\n
// المصفوفة الأصلية في الذاكرة: [A, B, C]\n// نقوم بإدراج X في الفهرس 1\n// الخطوة 1: الإزاحة: [A, B, C, undefined] (نخصص مساحة)\n// الخطوة 2: النسخ: [A, B, B, C] (نزيح B و C)\n// الخطوة 3: الإدراج: [A, X, B, C]\n// الخطوة 4: تحديث الطول

المدونات

توصيات الكتب