تقدّم المصفوفات توابِع عديدة تُسهِّل التعامل معها. ولتبسيطها سنقسّمها إلى مجموعات بحسب الوظيفة في هذا الفصل ونشرح كل منها على حدة.
إضافة العناصر وإزالتها
عرفنا من الفصل الماضي بالتوابِع التي تُضيف العناصر وتُزيلها من بداية أو نهاية المصفوفة:
arr.push(...items)– يُضيف العناصر إلى النهاية،arr.pop()– يستخرج عنصرًا من النهاية،arr.shift()يستخرج عنصرًا من البداية،g,arr.unshift(...items)– يُضيف العناصر إلى البداية.
وهذه أخرى غيرها.
الوصل splice
كيف نحذف أحد عناصر المصفوفة؟
المصفوفات كائنات، يمكننا تجربة delete وربما تنجح:
let arr = ["I", "go", "home"];
delete arr[1]; // remove "go"
alert(arr[1]); // undefined
// now arr = ["I", , "home"];
alert(arr.length); // 3
أُزيل العنصر صحيح، ولكنّ ما زال في المصفوفة ثلاثة عناصر، كما نرى في arr.length == 3.
هذا طبيعي، إذ يُزيل delete obj.key القيمة بمفتاحها key… وهذا فقط. ينفع للكائنات ربّما، لكنّا نريدها للمصفوفات أن تنتقل كل العناصر على اليمين وتأخذ الفراغ الجديد. أي أننا نتوقع أن تصغر المصفوفة الآن.
لهذا السبب علينا استعمال توابِع خاصّة لذلك.
The arr.splice method is a swiss army knife for arrays. It can do everything: insert, remove and replace elements.
هذه صياغته:
arr.splice(start[, deleteCount, elem1, ..., elemN])
It modifies arr starting from the index start: removes deleteCount elements and then inserts elem1, ..., elemN at their place. Returns the array of removed elements.
فهم هذا التابِع بالأمثلة أبسط.
فلنبدأ أولًا بالحذف:
let arr = ["I", "study", "JavaScript"];
arr.splice(1, 1); // from index 1 remove 1 element
alert( arr ); // ["I", "JavaScript"]
رأيت؟ سهلة. نبدأ من العنصر ذي الفهرس 1 ونُزيل عنصرًا واحدًا (1).
الآن، نُزيل ثلاثة عناصر ونستبدلها بعنصرين آخرين:
let arr = ["I", "study", "JavaScript", "right", "now"];
// أزِل الثلاث عناصر الأولى وعوّضها بتلك الأخرى
arr.splice(0, 3, "Let's", "dance");
alert( arr ) // now ["Let's", "dance", "right", "now"]
أمّا هنا فكيف يُعيد splice مصفوفةً بالعناصر المُزالة.
let arr = ["I", "study", "JavaScript", "right", "now"];
// أزِل أوّل عنصرين
let removed = arr.splice(0, 2);
alert( removed ); // "I", "study" <-- قائمة بالعناصر المُزالة
يمكن أن يُدرج تابِع splice العناصر دون إزالة أيّ شيء أيضًا. كيف؟ نضع deleteCount يساوي الصفر 0:
let arr = ["I", "study", "JavaScript"];
// from index 2
// delete 0
// then insert "complex" and "language"
arr.splice(2, 0, "complex", "language");
alert(arr); // "I", "study", "complex", "language", "JavaScript"
الفهارس السالبة ممكنة أيضًا يمكننا هنا وفي توابِع المصفوفات الأخرى استعمال الفهارس السالبة. وظيفتها تحديد المكان بدءًا من نهاية المصفوفة، هكذا:
```js run
let arr = [1, 2, 5];
// from index -1 (one step from the end)
// delete 0 elements,
// then insert 3 and 4
arr.splice(-1, 0, 3, 4);
alert( arr ); // 1,2,3,4,5
```
القطع slice
التابِع arr.slice أبسط بكثير من شبيهه arr.splice.
صياغته هي:
arr.slice([start], [end]);
وهو يُعيد مصفوفة جديدةً بنسخ العناصر من الفهرس start إلى end (باستثناء end). يمكن أن تكون start وحتّى end سالبتان، بهذا يُعدّ المحرّك القيمتان أماكن بدءًا من نهاية المصفوفة.
هذا التابِع يشبه تابِع السلاسل النصية str.slice، ولكن بدل السلاسل النصية الفرعية، يُعيد المصفوفات الفرعية. إليك المثال الآتي:
For instance:
let arr = ["t", "e", "s", "t"];
alert(arr.slice(1, 3)); // (نسخة تبدأ من 1 وتنتهي عند 3)
alert(arr.slice(-2)); // (نسخة تبدأ من -2 وتنتهي في النهاية)
يمكننا أيضًا استدعائها بلا وُسطاء: يُنشئ arr.slice()) نسخة عن arr. نستعمل هذا غالبًا لأخذ نسخة وإجراء تعديلات عليها دون تعديل المصفوفة الأصلية، وتركها كما هي.
الربط concat
يُنشئ التابِع [arr.concat] مصفوفةً جديدة فيها القيم الموجودة في المصفوفات والعناصر الأخرى.
صياغته هي:
arr.concat(arg1, arg2...)
وهو يقبل أيّ عدد من الوُسطاء، أكانت مصفوفات أو قيم. أمّا ناتجه هو مصفوفة جديدة تحوي العناصر من arr، ثم arg1 فَـ arg2 وهكذا دواليك. لو كان الوسيط argN نفسه مصفوفة، فستُنسخ كل عناصره، وإلّا فسيُنسخ الوسيط نفسه. لاحِظ هذا المثال:
let arr = [1, 2];
// اصنع مصفوفة فيها العنصرين: arr و [3,4]
alert(arr.concat([3, 4])); // 1,2,3,4
// اصنع مصفوفة فيها العناصر: arr و[3,4] و[5,6]
alert(arr.concat([3, 4], [5, 6])); // 1,2,3,4,5,6
// اصنع مصفوفة فيها العنصرين: arr و[3,4]، بعدها أضِف القيمتين 5 و 6
alert(arr.concat([3, 4], 5, 6)); // 1,2,3,4,5,6
عادةً تنسخ المصفوفة عناصر المصفوفات الأخرى. بينما الكائنات الأخرى (حتّى لو كانت مثل المصفوفات) فستُضاف كتلة كاملة.
let arr = [1, 2];
let arrayLike = {
0: "something",
length: 1
};
alert(arr.concat(arrayLike)); // 1,2,[object Object]
… ولكن لو كان للكائن الشبيه بالمصفوفات خاصية Symbol.isConcatSpreadable، فستتعامل معه concat مثلما تتعامل مع المصفوفات: ستُضاف عناصره بدل كيانه:
let arr = [1, 2];
let arrayLike = {
0: "something",
1: "else",
[Symbol.isConcatSpreadable]: true,
length: 2
};
alert( arr.concat(arrayLike) ); // 1,2,something,else
التكرار: لكلّ forEach
يتيح لنا التابِع arr.forEach تشغيل إحدى الدوال على كلّ عنصر من عناصر المصفوفة.
الصياغة:
arr.forEach(function(item, index, array) {
// ... استعملهما فيما تريد
});
مثال على عرض كلّ عنصر من عناصر المصفوفة:
// لكلّ عنصر، استدعِ دالة التنبيه alert
["Bilbo", "Gandalf", "Nazgul"].forEach(alert);
بينما هذه الشيفرة تحبّ الكلام الزائد ومكانها في المصفوفة المحدّدة:
["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
alert(`${item} is at index ${index} in ${array}`);
});
ناتج التابِع (لو أعادَ شيئًا أصلًا) يُهمل ويُرمى.