الدوال (Functions)

مقدمة

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

مشكلة تنفيذ الكود أكثر من مرة

في الحلقات التكرارية كنا نفذنا فكرة جمع اﻷعداد من 1 إلى 10، تتذكر صحيح؟ ولكن ماذا لو أردنا في نفس البرنامج تنفيذ نفس الكود أكثر من مره؟ نريده أن يقوم أيضاً بجمع اﻷعداد من 1 إلى 20 وطباعة الناتج، ولكن كيف؟ هل سنقوم بنسخ الكود المكون من 10 أسطر مثلاً وتكراره مره أخرى لتنفيذ نفس الشيء!! هنا يأتي دور الدوال! يمكنها حل المشكلة بكل بساطة.

مفهوم الدوال (Functions)

مفهوم الدوال بشكل عام

الدوال بشكل عام: هي عبارة عن شيء يدخل له مدخلات (بين اﻷقواس)، يقوم بإجراء عمليات عليها ثم يقوم بإخراج نواتج. ولكل دالة اسم تُعرف الدالة به ويتم استدعاءها به.

مفهوم الدوال برمجياً

هي كتلة من اﻷوامر تنفذ عند استدعاءها فقط.

عندما يمر المفسر على الدالة لا يقوم بتنفيذ كتلة اﻷوامر الخاصة بها، يقوم فقط بتعريف الدالة باسمها وحفظ كتلة اﻷوامر ليتم تنفيذها عندما تستدعى الدالة.

ويمكن إدخال بيانات للدالة تُعرف بـ مدخلات (parameters) ويمكن للدالة أن تقوم بإرجاع بيانات تُعرف بـ ناتج الدالة (result) كما سنتعلم في الدرس.

أهمية الدوال

المعلومات التالية نظرية بالتالي لا يجب فهمها كلياً لكن ستفهمها أكثر أثناء مراجعة الدرس

تتلخص أهمية الدوال في مقولة "اكتب الكود مرة واستخدمه عدة مرات"

  • تنفيذ كود محدد عدة مرات في البرنامج
  • هيكلة أفضل للبرامج: وهي عبارة عن تقسيم البرنامج إلى عدة دوال منفصلة عن بعضها، وغالباً تستخدمها البرامج متوسطة الحجم وسنتحدث بتعمق عن استخدام الدوال في درس الدوال (مستوى متوسط)
  • كود قابل لإعادة اﻹستخدام في برامج أخرى: فمثلاً ممكن أن تستخدم دالة مكتوبة سابقاً مهمتها كتابة اﻷرقام المالية بهذا الشكل: 25.00 بدلاً من كتابتها 25 وتقوم باستدعاء الدالة في كل مرة تحتاج لطباعة رقم مالي، ثم يمكنك استخدام الدالة في أي برنامج آخر لتنفذ مهمتها بدون أن تكرر أوامرها في كل مرة تحتاجها.

ومثلاً يمكن تطبيق نفس الفكرة السابقة في دالة تقوم بتحويل التاريخ من شكله العادي "2021-1-19" إلى "منذ يومين" ويمكنك استدعاء الدالة عند طباعة أي تاريخ في البرنامج لتبدله من الشكل العادي إلى "منذ ..."

شرح استخدام الدوال

تعريف الدالة (Define a function)

function name(/* المدخلات هنا */){
  // كتلة اﻷوامر هنا
  // تنفذ فقط عند استدعاء الدالة
}

استخدمنا التعليقات comments لشرح الكود السابق... /* */ و //

مم تتكون الدالة؟

  • function أمر تعريف الدالة
  • اسم الدالة: ويمكن أن يكون أي اسم، في الكود السابق اخترنا اسم الدالة name لكن يمكن كتابة أي اسم آخر
  • المدخلات (Parameters): وهي بيانات تدخل إلى الدالة، ويمكن أن تكون الدالة بدون مُدخلات
  • كتلة اﻷوامر: وهي عبارة عن كتلة أوامر (Block) يتم تنفيذها فقط عندما نستدعى الدالة، وبالتالي يمكن استدعاء الدالة أي عدد من المرات ليتم تنفيذ هذه الكتلة في كل مرة.

للدوال عدة أشكال سنذكرها في اﻷمثلة التالية لكن سنبدأ بالشكل البسيط للدالة بدون مدخلات أو ناتج، ويُستخدم في تكرار تنفيذ كتلة من اﻷوامر أو تنفيذها فقط عند استدعاءها.

مثال على دالة تقوم بطباعة "دليل مبرمج"

function printDalil(){
  console.log("دليل مبرمج");
}
إن قمت بتشغيل الكود السابق؛ لن تحصل على ناتج ﻷن الدالة تم تعريفها فقط، ولم يتم استدعاءها بعد.

استدعاء الدالة (Call a function)

يتم استدعاء الدالة عن طريق كتابة اسمها ثم وضع أقواس الدالة: name() وعندما يمر المفسر على أمر استدعاء الدالة فإنه يقوم بتنفيذ كتلة اﻷوامر الخاصة بالدالة، وبالتالي يمكن أن تحتوي كتلة أوامر الدالة على الكثير من اﻷوامر وننفذها مرة واثنين وثلاثة فقط عن طريق استدعاء الدالة!

مثال على استدعاء الدالة:

function printDalil(){
  console.log("دليل مبرمج");
}

printDalil();
ناتج التشغيل دليل مبرمج

ويمكن استدعاء الدالة أكثر من مره:

function printDalil(){
  console.log("دليل مبرمج");
}

printDalil();
printDalil();
printDalil();
ناتج التشغيل دليل مبرمج
دليل مبرمج
دليل مبرمج

إذا نسيت اﻷقواس () لن يتم استدعاء الدالة، وفي بعض لغات البرمجة سيعطي المفسر خطأ Error

مدخلات الدالة (Parameters)

في المثال السابق الدالة تقوم بتنفيذ أوامر محددة، مهمتها أن تُنفذ كتلة اﻷوامر عند استدعاءها، لكن في بعض اﻷحيان نحتاج لدوال تنفذ لنا عمليات على بيانات معينة، على سبيل المثال دالة ندخل لها عدد السنوات، فتقوم بطباعة عدد الشهور في هذه السنوات، كيف ننفذها؟ سنستخدم مدخلات الدالة في التنفيذ ﻷن عدد السنين يُعتبر مُدخل، وتوضع المدخلات بين اﻷقواس.

توضع مدخلات الدالة بين اﻷقواس، يمكنك تسميتها بأي اسم، وتتعامل داخل الدالة كأنها متغيرات، ويكون متاح لك استخدامها داخل الدالة، وإجراء أي عمليات عليها.
function getMonths(years){
  var months = years*12;
  console.log(months);
}

getMonths(2);
getMonths(5);
ناتج التشغيل 24
60

جرب استدعاء الدالة وإدخال أي عدد سنين آخر وانظر الناتج!

يمكن اختصار المثال السابق في الطباعة مباشرة بدلاً من إنشاء متغير months مثل: console.log(years*12)

اسم الدالة لا يمكن أن يحتوي على مسافات، لذلك نفصل بين الكلمتين عن طريق كتابة الحرف اﻷول كبير (كابيتال) مثل getMonth وفي بعض اللغات اﻷخرى يكون مشهور أكثر استعمال _ للفصل بين الكلمات، مثل get_month

إذا حددت للدالة مُدخلات parameters فلا تنسى إدخالها بين اﻷقواس عند استدعاء الدالة، وإلا لن تعمل الدالة كما تريدها أو في معظم لغات البرمجة سيعطي المفسر ايرور

مدخلات متعددة للدالة

يمكن أن تأخذ الدالة أي عدد من المُدخلات وليس مُدخل واحد، ونفصل بينهم بعلامة ,

علامة , موجودة أسفل لوحة المفاتيح يمين حرف M

مثال مساحة المستطيل

فمثلاً نريد إنشاء دالة تقوم بحساب مساحة المستطيل عن طريق إدخال الطول والعرض لها:

function area(width, height){
  console.log(width * height);
}

area(5,8);
ناتج التشغيل 40

المثال السابق يقوم بحساب مساحة مستطيل عرضه 5 وطوله 8، ويمكن تطبيق الدالة على أي مستطيل آخر بمجرد استدعاءها!

جرب المثال السابق على مساحة المربع، مع العلم أنها تساوي طول الضلع في نفسه.

مثال جمع ثلاثة أعداد

// This function takes 3 arguments and print sum of them
// هذه الدالة تأخذ ثلاثة مدخلات وتقوم بطباعة مجموعهم

function sum(x,y,z){
  console.log(x+y+z);
}
sum(2,3,5);
ناتج التشغيل 10

قمنا بتسمية الدالة sum() ويعني مجموع أو جمع، ودائما احرص على اختيار اسم للدالة يشرح عملها

احرص دائما قبل تعريف الدالة على كتابة بعض التعليقات comments تصف ما تقوم به الدالة - كما فعلنا في المثال السابق - بحيث إذا كانت الدالة طويلة يمكنك قراءة تعليقاتك عنها ومعرفة ما تقوم به الدالة بدون تحليل أكواد الدالة...

أمثلة على الدوال

حل مشكلة جمع اﻷعداد أكثر من مرة

ذكرنا في بداية الدرس مشكلة أننا نريد طباعة مجموع اﻷعداد من 1 إلى 10 ثم نريد تنفيذ نفس الكود على اﻷعداد من 1 إلى 20...

قمنا سابقاً بكتابة خوارزمية وكود طباعة مجموع اﻷعداد في درس الحلقات التكرارية وكان الكود كالتالي:

var i = 1;
var result = 0;

while (i <= 10){
  result = result + i;
  i = i + 1;
}

console.log(result);
ناتج التشغيل 55

الكود السابق يجمع مجموع اﻷعداد من 1 إلى 10

واﻵن نريد تنفيذ الكود السابق مرتين، مرة على الأعداد من 1 إلى 10 واﻷخرى على اﻷعداد إلى 20 وطباعة ناتج العمليتين، بدون الدوال سيبدوا الكود كالتالي:

var i = 1;
var result = 0;

while (i <= 10){
  result = result + i;
  i = i + 1;
}
console.log(result);

var n = 1;
var result2 = 0;

while (n <= 20){
  result2 = result2 + n;
  n = n + 1;
}
console.log(result2);
ناتج التشغيل 55
210

بالتأكيد شيء غير مقبول إطلاقاً أن يتم حل المشكلة بالطريقة السابقة وأن يبدوا الكود هكذا، فبالنسبة للمبرمجين تكرار سطر واحد ينفذ نفس الشيء مرتين هو من أسوء ما يمكن أن تقوم به كمبرمج على اﻹطلاق، فما بالك بتكرار كما في المثال السابق، ويزداد اﻷمر سوءاً إن أردت تنفيذ نفس الكود لمرة ثالثة على عدد آخر مثلا 30! وهنا يأتي دور الدوال لتحل المشكلة كما في الكود التالي

function sumTo(to){
  var i = 1;
  var result = 0;

  while (i <= to){
    result = result + i;
    i = i + 1;
  }
  console.log(result);
}

// calling sumTo function
sumTo(10);
sumTo(20);
ناتج التشغيل 55
210

وصلنا لنفس الناتج! جرب تنفيذ الدالة sumTo على اﻷعداد إلى 50 أيضاً وانظر الناتج.

دالة تحديد موجب أم سالب

مثال إنشاء دالة تطبع "موجب" إن كان العدد المُدخل موجب، وتطبع "سالب" إن كان العدد سالب غير ذلك يكون العدد صفر فتطبع صفر.

function posOrNeg(num){
  if (num > 0){
    console.log("موجب");
  }else{
    if (num < 0){
      console.log("سالب");
    }else{ 
      console.log("صفر");
    }
  }
}

posOrNeg(5);
posOrNeg(2);
posOrNeg(0);
posOrNeg(-2);
ناتج التشغيل موجب
موجب
صفر
سالب

تمارين على الدوال

معلومات أخرى عن الدوال

دالة الطباعة

لقد قمت باستخدام دالة الطباعة في الدروس السابقة، وهي من أشهر استخدامات الدوال، اﻵن يمكنك ربط ما تعلمت عن الدوال بدالة الطباعة... فهي عبارة عن دالة عامة معرفة مسبقاً مدمجة بمفسر جافاسكريبت، أي يمكن ﻷي كود استخدامها بدون تعريفها ﻷنها معرفة مسبقاً ومدمجة بمفسر اللغة، هذه الدالة اسمها log() وعند استدعاءها يدخل لها مُدخل وهو الشيء الذي تريد طباعته ثم تقوم بتنفيذ بعض اﻷوامر التي تطبع المُدخل، لا نحتاج لمعرفة ما هي اﻷوامر التي تنفذ ﻷنها شيء مرتبط بمفسر جافاسكريبت، لكن اﻷهم أن نعرف انها دالة، وتستعمل نفس أسلوب الدوال اﻷخرى! وتم تعريفها مرة واحدة ولكنك يمكنك بكتابة اسمها استدعاءها أي عدد من المرات بسهولة! حتى يمكنك اﻹستفادة منها بدون معرفة كيف تقوم بالطباعة.

console.log("test");

ستتعلم لماذا نكتب console. مع log() في درس الكائنات... وهو مفهوم متقدم لذلك انتظر حتى تتعلمها، فهنا console عبارة عن كائن.

الدوال الرياضية تتشابه مع الدوال البرمجية

نذكر مفهوم الدوال رياضياً لتبسيط وتوضيح معنى الدوال، يمكنك تخطي الكلام التالي..

للدوال استخدام في الرياضيات والجبر أيضاً وتشبه إلى حد كبير الدوال البرمجية، الفرق في اﻹستخدام فقط.

فمثلاً في الرياضيات للدالة اسم، وغالباً يكون "د" وكل دالة يدخل لها عدد، لتجري عملية حسابية أو علاقة رياضية عليه ثم ينتج عن الدالة ناتج! فمثلاً يقال الدالة د (س) = س + ٢، هي دالة رياضية اسمها د وتأخذ مدخل متغير س وتقوم بإرجاع ناتج جمع 2 على المتغير، فإن نفذنا الدالة د على 3 تكون د(٣) = ٣+٢ ويكون ناتج الدالة 5، كذلك يمكن تنفيذها على أي عدد.

لذلك الدوال مفهوم عام وليس برمجي فقط، وفي الرياضيات يتشابه جداً معه في البرمجة ويختلف اﻹستخدام ففي الرياضيات يستخدم لتنفيذ عملية جبرية، حسابية أو علاقة، وفي البرمجة يُستخدم لتنفيذ أوامر

المساهمين

وجدت خطأ أو تريد المساهمة في محتوى الدرس؟ عدل الصفحة على Github