كيفية التحقق من وجود عنصر في مصفوفة JavaScript؟ من «يعمل فقط» إلى «يطير»
\n\nهل سبق لك أن كتبت كودًا وتوقفت فجأة، ناظرًا إلى مصفوفة من البيانات؟ «هل يوجد هنا ما أحتاجه؟» — هذا السؤال يقلق كل مطور. على Stack Overflow، موضوع How do I check if an array includes a value in JavaScript حصد ملايين المشاهدات. وليس بدون سبب. تبدو المهمة بسيطة، لكن حلها لا يؤثر فقط على قابلية قراءة الكود، بل على سرعة عمل التطبيق بأكمله.
\n\nاليوم سنستعرض جميع طرق التحقق من وجود عنصر في مصفوفة JavaScript. لن نعرض الطرق فقط — بل سنجري تحقيقًا حقيقيًا في الأداء. ستعرف متى تستخدم includes()، ولماذا indexOf() أحيانًا أسرع، وكيف يمكن لـ Set تسريع كودك بعشرات المرات. هيا بنا!
الكلاسيكية: Array.prototype.includes()
\n\nالطريقة الأحدث والأكثر قابلية للقراءة هي طريقة includes(). ظهرت في ES2016 وسرعان ما أصبحت المعيار الفعلي. لماذا؟ لأن اسمها يتحدث عن نفسه.
\n\nconst fruits = ['apple', 'banana', 'mango', 'orange'];\nconst hasBanana = fruits.includes('banana');\nconsole.log(hasBanana); // true\n\nconst hasGrape = fruits.includes('grape');\nconsole.log(hasGrape); // false\n\n\nكل شيء بسيط وأنيق. تستخدم includes() المقارنة الصارمة (===)، لذا كن حذرًا مع أنواع البيانات:
const numbers = [1, 2, 3];\nconsole.log(numbers.includes('1')); // false — السلسلة لا تساوي الرقم\n\n\nالإيجابيات:
\n- \n
- قابلية القراءة 10/10 — الكود مفهوم حتى للمبتدئين \n
- تعمل مع
NaN(على عكسindexOf) \n - مدعومة من جميع المتصفحات الحديثة \n
السلبيات:
\n- \n
- تعقيد خطي O(n) — تمر عبر المصفوفة بأكملها \n
- غير مناسبة إذا كنت بحاجة إلى إيجاد فهرس العنصر \n
المخضرم: Array.prototype.indexOf()
\n\nقبل ظهور includes()، كان الجميع يستخدم indexOf(). هذه الطريقة تُرجع فهرس أول عنصر تم العثور عليه أو -1 إذا كان العنصر غير موجود.
const fruits = ['apple', 'banana', 'mango'];\nconst index = fruits.indexOf('banana');\nif (index !== -1) {\n console.log('تم العثور على العنصر في الموضع', index);\n} else {\n console.log('العنصر غير موجود');\n}\n\n\nاعتاد الكثيرون على هذا الفحص، ولا يزال يعمل. لكن هناك فارق مهم: indexOf() لا يستطيع العثور على NaN.
\n\nconst arr = [NaN];\nconsole.log(arr.indexOf(NaN)); // -1 — لا يعثر!\nconsole.log(arr.includes(NaN)); // true — يعثر\n\n\nهذا لأن NaN !== NaN في JavaScript، و indexOf يستخدم المقارنة الصارمة. بينما includes() تستخدم خوارزمية SameValueZero التي تعالج NaN بشكل صحيح.
متى تستخدم indexOf؟
\n- \n
- إذا كنت بحاجة إلى فهرس العنصر، وليس مجرد وجوده \n
- إذا كنت متأكدًا من عدم وجود NaN في المصفوفة \n
- في الكود القديم (Legacy) حيث لا يمكن استخدام ES2016+ \n
المقاتل المرن: Array.prototype.find() و findIndex()
\n\nعندما تحتاج إلى التحقق ليس فقط من الوجود، بل من تحقيق شرط، يأتي find() للإنقاذ. يقبل دالة رد اتصال (callback) ويعيد أول عنصر يحقق الشرط، أو undefined.
const users = [\n { id: 1, name: 'Alice', age: 25 },\n { id: 2, name: 'Bob', age: 30 },\n { id: 3, name: 'Charlie', age: 35 }\n];\n\nconst user = users.find(u => u.age > 28);\nconsole.log(user); // { id: 2, name: 'Bob', age: 30 }\n\n// التحقق من الوجود\nconst exists = users.find(u => u.id === 4) !== undefined;\nconsole.log(exists); // false