call و apply في جافا سكريبت: أهم الأخطاء وكيفية تجنبها

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

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

ابدأ الدورة

call و apply في جافا سكريبت: أهم الأخطاء وكيفية تجنبها



هل سبق لك أن نظرت إلى كود جافا سكريبت لشخص آخر ورأيت تركيبات غريبة مثل func.call(this, arg1, arg2) أو func.apply(this, [arg1, arg2])؟ وتساءلت: "ما الفرق في الأساس؟" إذا كان الأمر كذلك، فأنت لست وحدك. سؤال "ما الفرق بين call و apply؟" هو أحد أكثر الأسئلة شيوعًا على Stack Overflow بمئات الآلاف من المشاهدات. وهذا ليس من قبيل الصدفة.



الخلط بين call و apply هو فخ كلاسيكي للمبتدئين (وليس فقط). في هذه المقالة، لن نكتفي بشرح النظرية. سنحلل أهم 5 أخطاء حقيقية، ونوضح كيفية إصلاحها، ونقدم خوارزمية واضحة ستخلصك من الحيرة إلى الأبد. هيا بنا!



نبذة مختصرة: ما هما call و apply؟



قبل الغوص في الأخطاء، دعنا ننعش الأساسيات. الطريقتان call و apply هما طريقتان مدمجتان في الدوال في جافا سكريبت. مهمتهما الرئيسية هي تحديد سياق الاستدعاء (this) بشكل صريح للدالة. بمعنى آخر، تسمحان لك بقول: "أيها الدالة، تخيلي أنك تعملين مع هذا الكائن".



الصيغة:



func.call(context, arg1, arg2, ...);func.apply(context, [arg1, arg2, ...]);


الفرق الرئيسي:

  • call تقبل الوسائط مفصولة بفاصلة (قائمة).
  • apply تقبل الوسائط على شكل مصفوفة (أو كائن شبيه بالمصفوفة).


هذا كل شيء. هذا هو الاختلاف الوحيد. ولكن بسبب هذا "الأمر التافه" تنشأ معظم الأخطاء. دعنا نحللها.



أهم 5 أخطاء عند العمل مع call و apply



الخطأ رقم 1: الخلط في قائمة الوسائط (الأكثر شيوعًا!)



هذا هو "ملك" جميع الأخطاء. لقد كتبت دالة تتوقع وسائط واحدة تلو الأخرى، ولكنك مررت مصفوفة عبر call. أو العكس.



مثال كارثي:



function greet(greeting, punctuation) {    console.log(greeting + ', ' + this.name + punctuation);}

const user = { name: 'آنا' };

// خطأ: نمرر مصفوفة، لكننا نستخدم callgreet.call(user, ['مرحبًا', '!']); // الإخراج: "مرحبًا,! آنا,undefined" — هراء تام!


لماذا يحدث هذا؟ call تتوقع وسائط واحدة تلو الأخرى. لقد تلقت وسيطًا واحدًا - مصفوفة كاملة - ووضعتها في المتغير greeting. بقي punctuation غير معرف (undefined).



كيف تصلحه؟ استخدم apply إذا كانت البيانات موجودة بالفعل في مصفوفة:



greet.apply(user, ['مرحبًا', '!']); // الإخراج: "مرحبًا, آنا!" — صحيح!


أو قم بفرد المصفوفة باستخدام عامل الانتشار (المنهج الحديث):



greet.call(user, ...['مرحبًا', '!']); // يعمل أيضًا!


الخطأ رقم 2: نسيان أن apply تعمل مع الكائنات الشبيهة بالمصفوفة



يعتقد الكثيرون أن apply تقبل فقط مصفوفة حقيقية. في الواقع، هي تقبل أي كائن شبيه بالمصفوفة: يجب أن يحتوي على خاصية length ومفاتيح رقمية.



مثال:



function sum() {    let total = 0;    for (let i = 0; i < arguments.length; i++) {        total += arguments[i];    }    return total;}

// نمرر ليس مصفوفة، بل كائنًا مع lengthconst args = { 0: 5, 1: 10, 2: 15, length: 3 };

console.log(sum.apply(null, args)); // الإخراج: 30 — يعمل!


لكن كن حذرًا: إذا لم يكن للكائن خاصية length، فإن apply ستتجاهله ببساطة. هذا خطأ شائع عند العمل مع arguments (كائن قديم) أو مع NodeList.



الخطأ رقم 3: استخدام call/apply حيث يكفي استدعاء بسيط



أحيانًا يسيء المبتدئون استخدام

المدونات

توصيات الكتب