الدليل العملي لمصفوفات JavaScript: شرح أشهر الدوال مع أمثلة واضحة
مقدمة إلى مصفوفات JavaScript
تُعدّ المصفوفة Array من أهم هياكل البيانات في البرمجة، لأنها تتيح تخزين مجموعة من العناصر داخل متغير واحد بطريقة منظّمة وسهلة المعالجة. في لغة JavaScript تُستخدم المصفوفات بكثرة عند التعامل مع القوائم، والبيانات الديناميكية، ونتائج API، وبُنى الواجهات التفاعلية.
في هذا الدليل ستتعرّف إلى مفهوم المصفوفات، وكيفية إنشائها، والوصول إلى عناصرها، وإضافة البيانات وحذفها، ثم الانتقال إلى أشهر دوال المصفوفات مثل map() وfilter() وreduce() مع أمثلة عملية تساعدك على الفهم والتطبيق.

ما هي المصفوفة في JavaScript؟
المصفوفة هي مجموعة مرتبة من العناصر، وتُكتب بين قوسين مربعين []، مع الفصل بين العناصر بفاصلة ,. وتمتاز مصفوفات JavaScript بمرونة عالية، إذ يمكن أن تحتوي على أنواع بيانات مختلفة داخل المصفوفة نفسها.
مثال على مصفوفة تضم أرقاماً وقِيَماً منطقية ونصوصاً وكائناً:
const mixedTypedArray = [100, true, 'freeCodeCamp', {}];
لكل عنصر داخل المصفوفة موضع يُعرف باسم index، ويبدأ العد دائماً من 0. هذا يعني أن أول عنصر يقع عند index 0، والثاني عند index 1، وهكذا.
أما عدد العناصر فيُعرف عبر الخاصية length. ومن المهم معرفة أن مصفوفات JavaScript ليست ثابتة الطول، بل يمكن تعديلها أثناء تشغيل البرنامج.
كيفية إنشاء مصفوفة في JavaScript
الطريقة المباشرة باستخدام الأقواس المربعة
هذه هي الطريقة الأكثر شيوعاً ووضوحاً:
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
استخدام الباني Array
يمكن أيضاً إنشاء المصفوفة عبر الباني Array:
const salad = new Array('🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑');
لكن انتبه إلى هذا الفرق المهم:
new Array(2)ينشئ مصفوفة طولها2، لكن عناصرها غير معرّفة.new Array(1, 2)ينشئ مصفوفة تحتوي فعلياً على العنصرين1و2.
كما توجد طرق حديثة ومفيدة مثل Array.of() وArray.from()، بالإضافة إلى عامل الانتشار ....
الوصول إلى عناصر المصفوفة
يمكنك الوصول إلى أي عنصر باستخدام الفهرس index داخل الأقواس المربعة:
const element = array[index];
مثال عملي:
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
salad[0]; // '🍅'
salad[2]; // '🥦'
salad[5]; // '🥕'
الوصول إلى العناصر من نهاية المصفوفة
قبل توفر بعض الأساليب الحديثة، كان الوصول إلى آخر عنصر يعتمد غالباً على الخاصية length:
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
const len = salad.length;
salad[len - 1]; // '🥑'
salad[len - 3]; // '🌽'
التكرار على عناصر المصفوفة
يمكنك استعراض العناصر باستخدام حلقة for أو forEach() أو غيرهما:
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
for (let i = 0; i < salad.length; i++) {
console.log(`Element at index ${i} is ${salad[i]}`);
}

إضافة عناصر إلى المصفوفة
الإضافة في نهاية المصفوفة باستخدام push()
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
salad.push('🥜');
ستصبح المصفوفة كالتالي:
["🍅", "🍄", "🥦", "🥒", "🌽", "🥕", "🥑", "🥜"]
الإضافة في بداية المصفوفة باستخدام unshift()
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
salad.unshift('🥜');
والنتيجة:
["🥜", "🍅", "🍄", "🥦", "🥒", "🌽", "🥕", "🥑"]
حذف عناصر من المصفوفة
حذف آخر عنصر باستخدام pop()
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
salad.pop(); // 🥑
console.log(salad); // ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕']
حذف أول عنصر باستخدام shift()
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
salad.shift(); // 🍅
console.log(salad); // ['🍄', '🥦', '🥒', '🌽', '🥕', '🥑']
نسخ المصفوفة واستنساخها
النسخ باستخدام slice()
إذا أردت إنشاء نسخة سطحية shallow copy من المصفوفة دون تعديل الأصل، فاستخدم slice():
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
const saladCopy = salad.slice();
console.log(saladCopy);
// ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑']
salad === saladCopy; // false
النسخ باستخدام عامل الانتشار ...
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
const saladCloned = [...salad];
console.log(saladCloned);
// ["🍅", "🍄", "🥦", "🥒", "🌽", "🥕", "🥑"]
هذه الطريقة عملية جداً، لكنها أيضاً تُنتج نسخة سطحية فقط.
التحقق مما إذا كانت القيمة مصفوفة
قد تصادف بيانات غير واضحة المصدر، وهنا يفيد استخدام Array.isArray():
Array.isArray(['🍅', '🍄', '🥦']); // true
Array.isArray('🍅'); // false
Array.isArray({ tomato: '🍅' }); // false
Array.isArray([]); // true
تفكيك المصفوفات Array Destructuring
وفرت ES6 صيغة مريحة لاستخراج قيم متعددة من المصفوفة وإسنادها مباشرة إلى متغيرات.
let [tomato, mushroom, carrot] = ['🍅', '🍄', '🥕'];
console.log(tomato, mushroom, carrot); // 🍅 🍄 🥕
وبدون هذا الأسلوب ستحتاج إلى كتابة أكثر:
let vegetables = ['🍅', '🍄', '🥕'];
let tomato = vegetables[0];
let mushroom = vegetables[1];
let carrot = vegetables[2];
تعيين قيمة افتراضية
let [tomato, mushroom = '🍄'] = ['🍅'];
console.log(tomato); // '🍅'
console.log(mushroom); // '🍄'
تخطي عنصر غير مطلوب
let [tomato, , carrot] = ['🍅', '🍄', '🥕'];
console.log(tomato); // '🍅'
console.log(carrot); // '🥕'
تفكيك المصفوفات المتداخلة
let fruits = ['🍈', '🍍', '🍌', '🍉', ['🍅', '🍄', '🥕']];
للوصول إلى العنصر '🥕' يمكن كتابة:
fruits[4][2]; // returns '🥕'
أو باستخدام التفكيك:
let [,,,, [,, carrot]] = ['🍈', '🍍', '🍌', '🍉', ['🍅', '🍄', '🥕']];
عامل الانتشار Spread ومعامل الباقي Rest
استخدام Rest Parameter
عندما يظهر ... في الجهة اليسرى من التفكيك، فإنه يجمع العناصر المتبقية في مصفوفة جديدة:
const [tomato, mushroom, ...rest] = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
console.log(tomato); // '🍅'
console.log(mushroom); // '🍄'
console.log(rest); // ["🥦", "🥒", "🌽", "🥕", "🥑"]
استخدام Spread Operator
عندما يظهر ... في الجهة اليمنى، فإنه ينشر عناصر المصفوفة:
const salad = ['🍅', '🍄', '🥦', '🥒', '🌽', '🥕', '🥑'];
const saladCloned = [...salad];
salad === saladCloned; // false
تبديل القيم بسهولة
let first = '😔';
let second = '🙂';
[first, second] = [second, first];
console.log(first); // '🙂'
console.log(second); // '😔'
دمج مصفوفتين أو أكثر
const emotion = ['🙂', '😔'];
const veggies = ['🥦', '🥒', '🌽', '🥕'];
const emotionalVeggies = [...emotion, ...veggies];
console.log(emotionalVeggies);
ملخص سريع لأشهر الخصائص والدوال الأساسية
push(): إضافة عنصر إلى نهاية المصفوفة.unshift(): إضافة عنصر إلى بداية المصفوفة.pop(): حذف آخر عنصر.shift(): حذف أول عنصر.slice(): إنشاء نسخة سطحية من المصفوفة.Array.isArray(): التحقق من كون القيمة مصفوفة.length: معرفة عدد العناصر.
دوال المصفوفات المهمة في JavaScript
الدالة concat()
تُستخدم لدمج مصفوفتين أو أكثر دون تعديل المصفوفات الأصلية:
const first = [1, 2, 3];
const second = [4, 5, 6];
const merged = first.concat(second);
console.log(merged); // [1, 2, 3, 4, 5, 6]
const third = [7, 8, 9];
const mergedAll = first.concat(second, third);
console.log(mergedAll); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
الدالة join()
تحوّل عناصر المصفوفة إلى سلسلة نصية واحدة باستخدام فاصل تحدده أنت:
const emotions = ['🙂', '😍', '🙄', '😟'];
const joined = emotions.join();
console.log(joined); // "🙂,😍,🙄,😟"
const customJoined = emotions.join('<=>');
console.log(customJoined); // "🙂<=>😍<=>🙄<=>😟"
[].join(); // ""
الدالة fill()
تملأ المصفوفة بقيمة ثابتة، مع إمكانية تحديد بداية ونهاية التعديل:
const colors = ['red', 'blue', 'green'];
colors.fill('pink');
console.log(colors); // ["pink", "pink", "pink"]
const moreColors = ['red', 'blue', 'green'];
moreColors.fill('pink', 1, 3);
console.log(moreColors); // ["red", "pink", "pink"]
الدالة includes()
تتحقق مما إذا كانت المصفوفة تحتوي على عنصر معين:
const names = ['tom', 'alex', 'bob', 'john'];
names.includes('tom'); // true
names.includes('july'); // false
الدالتان indexOf() وlastIndexOf()
تحددان موضع العنصر داخل المصفوفة:
const names = ['tom', 'alex', 'bob', 'john'];
names.indexOf('alex'); // 1
names.indexOf('rob'); // -1
const repeatedNames = ['tom', 'alex', 'bob', 'tom'];
repeatedNames.indexOf('tom'); // 0
repeatedNames.lastIndexOf('tom'); // 3
الدالة reverse()
تعكس ترتيب العناصر وتعدّل المصفوفة الأصلية:
const names = ['tom', 'alex', 'bob'];
names.reverse(); // ["bob", "alex", "tom"]
الدالة sort()
من أكثر الدوال استخداماً، لكنها تحتاج فهماً جيداً. افتراضياً، تقوم sort() بتحويل القيم إلى نصوص ثم ترتبها تصاعدياً. لذلك قد تعطي نتائج غير متوقعة مع الأرقام.
const names = ['tom', 'alex', 'bob'];
names.sort();
// ["alex", "bob", "tom"]
أما مع الأرقام:
const numbers = [23, 5, 100, 56, 9, 13, 37, 10, 1];
numbers.sort();
// [1, 10, 100, 13, 23, 37, 5, 56, 9]
هذا السلوك يحدث لأن الترتيب الافتراضي يعتمد على مقارنة النصوص. والحل يكون بتمرير دالة مقارنة:
function ascendingComp(a, b) {
return a - b;
}
numbers.sort(ascendingComp);
// [1, 5, 9, 10, 13, 23, 37, 56, 100]
numbers.sort((a, b) => b - a);
// ترتيب تنازلي
الدالة splice()
تُستخدم لإضافة عناصر أو حذفها أو استبدالها داخل المصفوفة الأصلية. وهي من أقوى الدوال، لكنها تتطلب الانتباه إلى ترتيب الوسائط.
إضافة عنصر
const names = ['tom', 'alex', 'bob'];
names.splice(1, 0, 'zack');
console.log(names); // ["tom", "zack", "alex", "bob"]
حذف عنصر واستبداله
const names = ['tom', 'alex', 'bob'];
const deleted = names.splice(2, 1, 'zack');
console.log(deleted); // ["bob"]
console.log(names); // ["tom", "alex", "zack"]
الدوال الثابتة للمصفوفات Static Array Methods
الدالة Array.from()
من المشكلات الشائعة في الويب التعامل مع كائنات تشبه المصفوفات لكنها ليست مصفوفات فعلية، مثل HTMLCollection. لهذا السبب نستخدم Array.from() لتحويلها إلى مصفوفة حقيقية.
مثال HTML:
<div id="main">
<ul>
<ol type="1">
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
</ol>
</ul>
</div>
عند تنفيذ:
document.getElementsByTagName('li');
ستحصل على HTMLCollection:

وإذا حاولت استخدام forEach() مباشرة فقد يظهر خطأ:
document.getElementsByTagName('li').forEach(() => {
// Do something here..
});


الحل:
const collection = Array.from(document.getElementsByTagName('li'));
الآن أصبح collection مصفوفة فعلية:

الدالة Array.of()
تنشئ مصفوفة جديدة من أي عدد من العناصر وبأي أنواع:
Array.of(2, false, 'test', { name: 'Alex' });

دوال التكرار على المصفوفات Array Iterator Methods
هذه الفئة من الدوال بالغة الأهمية، لأنها تمكّنك من معالجة البيانات بشكل نظيف ومقروء. سنستخدم المصفوفة التالية التي تحتوي على بيانات طلاب مسجلين في دورات مدفوعة:
let students = [
{
id: 1,
f_name: 'Alex',
l_name: 'B',
gender: 'M',
married: false,
age: 22,
paid: 250,
courses: ['JavaScript', 'React']
},
{
id: 2,
f_name: 'Ibrahim',
l_name: 'M',
gender: 'M',
married: true,
age: 32,
paid: 150,
courses: ['JavaScript', 'PWA']
},
{
id: 3,
f_name: 'Rubi',
l_name: 'S',
gender: 'F',
married: false,
age: 27,
paid: 350,
courses: ['Blogging', 'React', 'UX']
},
{
id: 4,
f_name: 'Zack',
l_name: 'F',
gender: 'M',
married: true,
age: 36,
paid: 250,
courses: ['Git', 'React', 'Branding']
}
];
الدالة filter()
تنشئ مصفوفة جديدة تضم العناصر التي تحقق شرطاً معيناً:
const femaleStudents = students.filter((element, index) => {
return element.gender === 'F';
});
console.log(femaleStudents);

الدالة map()
تُستخدم لإنشاء مصفوفة جديدة بعد تطبيق تحويل على كل عنصر:
const fullNames = students.map((element, index) => {
return {
fullName: element['f_name'] + ' ' + element['l_name']
};
});
console.log(fullNames);

الدالة reduce()
تطبّق دالة تراكمية على عناصر المصفوفة لإنتاج قيمة واحدة نهائية:
const total = students.reduce((accumulator, student, currentIndex, array) => {
accumulator = accumulator + student.paid;
return accumulator;
}, 0);
console.log(total); // 1000
تُعد reduce() ممتازة لحساب الإجماليات، وبناء الكائنات، وتجميع النتائج المعقدة.
الدالة some()
تُرجع قيمة منطقية true إذا حقق عنصر واحد على الأقل الشرط:
let hasStudentBelow30 = students.some((element, index) => {
return element.age < 30;
});
console.log(hasStudentBelow30); // true
الدالتان find() وfindIndex()
تعيد find() أول عنصر يطابق الشرط، بينما تعيد findIndex() موضعه:
const student = students.find((element, index) => {
return element.age < 30;
});
console.log(student);

الدالة every()
تتحقق مما إذا كانت جميع عناصر المصفوفة تستوفي الشرط:
const atLeastTwoCourses = students.every((elements, index) => {
return elements.courses.length >= 2;
});
console.log(atLeastTwoCourses); // true
الدالة at() للوصول المرن إلى العناصر
أصبحت الدالة at() من الإضافات المفيدة في JavaScript، لأنها تسمح بالوصول إلى العناصر عبر فهارس موجبة أو سالبة، وهو ما يجعل قراءة الكود أوضح عند التعامل مع آخر عناصر المصفوفة.
const junkFoodILove = ['🥖', '🍔', '🍟', '🍕', '🌭', '🥪', '🌮', '🍿'];
junkFoodILove.at(0); // 🥖
junkFoodILove.at(3); // 🍕
junkFoodILove.at(-1); // 🍿
junkFoodILove.at(-5); // 🍕
junkFoodILove.at(-8); // 🥖
junkFoodILove.at(10); // undefined

أفضل ممارسات عند التعامل مع المصفوفات
- استخدم
map()عندما تريد تحويل البيانات دون تعديل الأصل. - استخدم
filter()عند الحاجة إلى استخراج مجموعة فرعية من العناصر. - تجنب الاعتماد على
sort()الافتراضية مع الأرقام من دون دالة مقارنة. - افهم الفرق بين الدوال التي تعدّل المصفوفة الأصلية مثل
splice()وreverse()وsort()، والدوال غير المعدّلة مثلconcat()وslice()وmap(). - عند نسخ مصفوفة من الكائنات، تذكّر أن النسخ السطحي لا ينسخ الكائنات الداخلية بعمق.
الخلاصة التقنية
مصفوفات JavaScript ليست مجرد وسيلة لتخزين البيانات، بل هي حجر أساس في بناء المنطق البرمجي الحديث داخل الواجهات والتطبيقات. كلما أتقنت دوال مثل filter() وmap() وreduce() وsplice()، أصبحت قادراً على كتابة كود أكثر وضوحاً وكفاءة وقابلية للصيانة. ومن الناحية العملية، فإن فهم الفرق بين الدوال التي تُنشئ نسخة جديدة وتلك التي تعدّل المصفوفة الأصلية هو ما يميز المطور المتمكن عن المبتدئ.