Menu
العربية

تعريف الدوال في JavaScript: الصياغة والرفع والإرجاع

تعرّف على كيفية تعريف الدوال في JavaScript: الكلمة المفتاحية function، المعاملات، قيم الإرجاع، الرفع (Hoisting)، والفرق بين التصريح والتعبير.

الدالة: كتلة من الخطوات لها اسم

في كل مرة تريد فيها أن تعطي مجموعة من الأوامر اسمًا وتعيد استخدامها، فأنت بحاجة إلى دالة. والطريقة الأقدم والأبسط لتعريف الدالة في جافا سكريبت هي ما يُعرف بـ function declaration، أي استخدام الكلمة المفتاحية function متبوعةً باسم الدالة.

index.js
Output
Click Run to see the output here.

لو قرأنا السطر من اليمين لليسار (أو بالمعنى المنطقي للكود):

  • function هي الكلمة المفتاحية التي تبدأ بها تعريف الدالة.
  • greet هو اسم الدالة.
  • (name) قائمة المعاملات (parameters) — أي المدخلات التي تستقبلها الدالة.
  • الكتلة الموجودة بين الأقواس المعقوفة هي جسم الدالة (body).
  • greet("Ada") هذا يُسمى استدعاء للدالة. هنا تُنفّذ جافا سكريبت جسم الدالة بعد أن تربط name بالقيمة "Ada".

تعريف الدالة لا يعني تشغيلها. ما يُشغّلها فعلًا هو الاستدعاء.

المعاملات والوسائط (Parameters vs Arguments)

كلمة parameter (معامل) تُطلق على الاسم الموجود داخل تعريف الدالة. أما argument (وسيط) فهي القيمة التي تُمرّرها فعليًا عند استدعاء الدالة. في الحديث اليومي كثير من المطورين يستخدمون الكلمتين بالتبادل، لكن التفريق بينهما يصبح مهمًا عند قراءة رسائل الخطأ وفهمها.

index.js
Output
Click Run to see the output here.

هنا base وexponent هما المعاملان (parameters)، أما 2 و10 فهما الوسيطتان (arguments) اللتان نمررهما. تربط جافا سكريبت بينهما بالترتيب: الوسيطة الأولى تذهب إلى المعامل الأول، وهكذا.

وعلى عكس بعض اللغات، لا تُصدر جافا سكريبت أي خطأ إذا مرّرت عدداً خاطئاً من الوسائط. فالوسائط الناقصة تأخذ القيمة undefined، والزائدة يجري تجاهلها بصمت. هذه المرونة مريحة، لكنها أحياناً تكون فخاً — وسنرى لاحقاً القيم الافتراضية ومعاملات الـ rest في دروس قادمة.

إرجاع القيم باستخدام return

الدالة console.log تطبع المخرجات على الشاشة، أما return فتُعيد قيمة إلى الجهة التي استدعت الدالة كي تستفيد منها:

index.js
Output
Click Run to see the output here.

بدون return، تُرجع الدالة القيمة undefined:

index.js
Output
Click Run to see the output here.

return كمان بتخرج من الدالة فوراً. الـ early return هو الأسلوب المعتمد للتعامل مع الحالات الاستثنائية قبل الدخول في المنطق الأساسي:

index.js
Output
Click Run to see the output here.

الـ Early Returns تمنع جسم الدالة من التحول إلى هرم متداخل من if/else.

الـ Hoisting: استدعِ الدالة قبل أن تُعرِّفها

هنا شيء يفاجئ فعلاً القادمين من لغات أخرى. تعريفات الدوال (Function Declarations) تخضع لما يُعرف بـ الرفع أو hoisting — أي أن جافا سكريبت ترفعها إلى أعلى نطاقها قبل أن تبدأ تنفيذ أي كود. هذا يعني أنه بإمكانك استدعاء الدالة في سطر يسبق سطر تعريفها:

index.js
Output
Click Run to see the output here.

الكود بالأعلى يشتغل تمامًا. قبل تنفيذ البرنامج، محرك جافا سكريبت يمرّ على الـ scope ويسجّل square كدالة، وبعدها يبدأ ينفّذ الأسطر واحدًا واحدًا من الأعلى للأسفل.

هذا فرق حقيقي في السلوك بين function declaration والطرق الأخرى لتعريف الدالة في جافا سكريبت (مثل function expression والدوال السهمية). هذه الأخيرة تخضع لعملية hoisting مثل المتغيرات تمامًا، يعني الاسم يكون معروفًا لكن القيمة لا تُسنَد إلا عند الوصول للسطر نفسه أثناء التنفيذ. سنعود لهذه النقطة بتفصيل أكثر بعد قليل.

على كل حال، أغلب دلائل الأسلوب (style guides) تنصح بتعريف الدالة قبل استدعائها. اعتبر أن الـ hoisting مجرد شبكة أمان، لا أسلوب برمجة تعتمد عليه.

الفرق بين function declaration و function expression

تعريف الدالة (function declaration) يقف بذاته كجملة مستقلة، أما تعبير الدالة (function expression) فيظهر في أي موضع يُتوقَّع فيه قيمة، وغالبًا ما يكون بعد علامة الإسناد = في تعريف متغير:

index.js
Output
Click Run to see the output here.

كلاهما ينتج دوال قابلة للاستدعاء. الفروقات:

  • الـ declarations يتم رفعها (hoisting) بالكامل، بينما الـ expressions تتبع قواعد الرفع الخاصة بالمتغير المُسنَدة إليه (const و let يبقيان في المنطقة الميتة المؤقتة حتى تُنفَّذ السطر).
  • الـ declaration لازم يكون لها اسم، أما الـ expression فيمكن أن تكون مجهولة (anonymous)، مع أن تسميتها يسهّل تتبّع الأخطاء في stack traces.
  • الـ declarations لا يمكن كتابتها في أي مكان. في الوضع الصارم (strict mode)، كتابة function foo() {} داخل بلوك if يتصرّف بشكل غير متّسق بين المحرّكات المختلفة — استخدم expression في هذه الحالة.

بالنسبة لمعظم الدوال المساعدة على المستوى الأعلى في الملف، تُقرأ الـ declaration بشكل جميل. أما الدوال التي تُمرَّر كوسائط أو تُسنَد إلى خصائص، فالخيار المعتاد هو الـ expression (أو دالة سهمية arrow function).

التسمية والأسلوب

اسم الدالة هو وعد بما تفعله الدالة. إنفاق بضعة أحرف إضافية لاختيار اسم وصفي يوفّر عليك الكثير أول مرة يقرأ فيها شخص ما الكود.

index.js
Output
Click Run to see the output here.

بعض الأعراف التي يُستحسن اتّباعها:

  • أسماء الدوال يجب أن تكون أفعالاً: fetchProfile، computeTotal، sendEmail.
  • استخدم نمط camelCase — فهو السائد في جافا سكريبت.
  • الدوال التي تُرجع قيمة منطقية (boolean) غالباً ما تبدأ بـ is أو has أو can، مثل: isValid، hasAccess، canEdit.

الهدف أن يُقرأ استدعاء الدالة وكأنه جملة مفيدة.

مثال عملي مبسّط

لنجمع كل ما سبق في مكان واحد — المعاملات، والخروج المبكر عبر return، واسم يُعبّر عن وظيفة الدالة:

index.js
Output
Click Run to see the output here.

تعريف واحد، وشرط حماية، ثم return واضح. هذا الشكل البسيط يغطي معظم الدوال التي ستكتبها فعلياً.

التالي: Arrow Functions

تعريف الدالة بالصيغة التقليدية (function declaration) هو الأساس الذي يعتمد عليه معظم الكود، لكن جافا سكريبت الحديثة تميل كثيراً إلى صيغة أقصر وأخف — وهي الدوال السهمية (arrow functions) — خاصة في الـ callbacks والدوال المختصرة من سطر واحد. شكلها مختلف، وسلوكها مع this مختلف أيضاً، وهذا هو محور الصفحة التالية.

الأسئلة الشائعة

كيف نُعرِّف دالة في JavaScript؟

تُستخدم الكلمة المفتاحية function متبوعة باسم الدالة، ثم قوسين للمعاملات، ثم كتلة التعليمات بين {}. مثال: function greet(name) { return 'Hi, ' + name; }. ولاستدعائها نكتب اسمها متبوعًا بالأقواس هكذا: greet('Ada').

ما المقصود بـ Hoisting في دوال JavaScript؟

تصريحات الدوال (function declarations) تُرفع إلى أعلى النطاق الذي تنتمي إليه قبل تنفيذ الكود، ولهذا يمكنك استدعاء الدالة في سطر يسبق مكان تعريفها. هذه القاعدة تنطبق فقط على تصريحات function، أما تعبيرات الدوال (function expressions) والدوال السهمية المُسنَدة إلى let أو const فلا تخضع لنفس سلوك الرفع.

ما الفرق بين function declaration و function expression؟

التصريح (declaration) عبارة مستقلة بذاتها مثل function greet() {} ويخضع للرفع الكامل. أما التعبير (expression) فهو إسناد دالة إلى متغيّر مثل const greet = function() {} ويتبع قواعد رفع المتغيّرات العادية. التصريحات لها اسم دائمًا، في حين أن التعبيرات كثيرًا ما تكون مجهولة الاسم (anonymous).

تعلّم البرمجة مع Coddy

ابدأ الآن