الدوال Functions في جافاسكريبت


محمد أحمد العيل

تخيّل أنك تعيش في قرية لا تتوفّر على شبكة مياه. تحتاج، للحصول على الماء، لأخذ سطل فارغ والذهاب إلى بئر وسط القرية وسحب المياه من البئر ثم العودة إلى المنزل.

تعاود الكرة مرات عدّة في اليوم، حسب حاجتك للمياه. سيكون شرحُ ما تفعله بالتفصيل في كل مرة تُسأل فيها عن الأمر مضيعة للوقت؛ لذا بدلا من أن تقول “آخذ سطلا فارغا وأذهب إلى البئر وسط المدينة، ثم أسحب دلوا من الماء من البئر وأفرغه في السطل وأعود”، بدلا من ذلك تجيب اختصارا “أجلب الماء”.

لقد أنشأت بهذه الإجابة دالة برمجية Function.

تعريف الدوالّ

الدالة هي كتلة من الأسطر البرمجية التي تنفّذ مجموعة من المهامّ وفق ترتيب محدَّد، مثلا: “آخذ السطل، أذهب إلى البئر، أسحب الماء منه وأعود”.

تُعرَّف الدالة بالصياغة التالية:

function functionName (parameters) {
  // نفّذ المهام هنا
}
  • function هي الكلمة المفتاحية التي تخبر جافاسكريبت أنك بصدد الإعلان عن دالة.
  • functionName هو اسمُ الدالة. في المثال أعلاه فإن اسم الدالة يمكن أن يكون drawWater (اغرف الماء). يمكن أن يكون اسمُ الدالة أيا اسم تختاره ما دام يحترم شروط أسماء المتغيّرات، أي:
    • أن يكون كلمة واحدة،
    • أن يتكوّن فقط من حروف لاتينية (a-z, A-Z)، أرقام (0-9) أو علامة تسطير سفلي _.
    • أن لا يكون كلمة محجوزة Reserved keywords في جافاسكريبت.
  • المعاملات Parameters هي مجموعة من المتغيّرات تفصل بينها فاصلة لاتينية , تريد تعريفها للاستخدام داخل الدالة. المعاملات اختيارية ويمكن تعريف دالة دون معاملات.

استخدام الدوالّ

يمكن استخدامُ الدالة بعد تعريفها. تدلّ العبارات “استخدام الدالة”، “تنفيذ الدالة” أو “استدعاء الدالة” على الشيء ذاته. لاستدعاء الدالة نكتُب اسمَها متبوعا بقوسين (). في ما يلي مثال نعرّف فيه دالة باسم sayHello ثم نستخدمها:

// تعريف الدالة
function sayHello () {
  console.log('Hello world!')
}

// استدعاء الدالة
sayHello()

ينتُج عن تنفيذ الدالة بالطريقة المشروحة أعلاه طباعةُ العبارة Hello world.

الإزاحة The indentation

يجب إزاحة جميع الأسطُر البرمجية الموجودة في كتلة، أي تقع بين قوسين معكوفين {}، إلى اليمين. هذه الممارسة مهمّة جدا وتساعد في تسهيل قراءة الشفرة البرمجية وصيانتها، وتمكّنك بنظرة واحدة معرفة أن التعليمة console.log('Hello world') هي جزء من الدالة sayHello:

function sayHello () {
  // تعليمة console.log أدناه مزاحة قليلا إلى اليمين وبالتالي فهي جزء من الدالة sayHello
  console.log('Hello world!')
}

يمكنك استخدام مسافتيْن (زر المسافة في لوحة المفاتيح مرتيْن) أو مفتاح الجدولة في لوحة المفاتيح Tab لإزاحة التعليمات في الشفرة. يفضّل بعض المطوّرين مفتاح الجدولة في ما يُفضّل آخرون المسافتين. استخدم أيهما تراه مناسبا، مع التأكد من استخدام نفس طريقة الإزاحة في كامل الشفرة.

المعاملات

تأخذ معظم الدوال معاملات، وهي عبارة عن سلسلة من المتغيّرات تفصل بينها فاصلة ,، تُعرَّف لتُستخدَم داخل الدالة. يمكنك تعريف معاملات بالعدد الذي تريد.

function functionName(param1, param2, param3) {
  // نفّذ المهام هنا
}

تُسنَد القيم إلى المعاملات بتمريرها بين قوسين إلى الدالة في سلسلة تفصل بينها فاصلة ,. تُسمَّى القيم المُمرَّرة إلى الدالة بالمعطيات Arguments. يُسنَد المعطى الأول إلى المعامل الأول، والمعطى الثاني إلى المعامل الثاني وهكذا:

functionName('arg1', 'arg2')

فلنشرح الأمر أكثر بمثال. فلنقل إنك تريد تعريف دالة باسم sayName وظيفتها تسجيل الاسم الشخصي والاسم العائلي لشخص. تبدو الدالة بالشكل التالي:

function sayName(firstName, lastName) {
  console.log('اسمك الشخصي هو ' + firstName)
  console.log('اسمك العائلي هو ' + lastName)
}

تُعرّف الدالة معاملين هما firstName وlastName. فلنفترض أن الاسم الشخصي هو “محمد” والاسم العائلي هو “عيسى”. لجعل الدالة تعمل على النحو المرغوب نمرّر لها المعطييْن محمد وعيسى كالتالي:

sayName('محمد', 'عيسى')

نحصُل بعد تنفيذ الدالة بالطريقة أعلاه على النتيجة التالية:

اسمك الشخصي هو محمد
اسمك العائلي هو عيسى

عند تعريف معامل أثناء تعريف الدالة ثم استخدام الدالة دون تمرير معطيات فإن المعامل سيأخذ القيمة “غير معرَّف” undefined:

sayName()

النتيجة:

// اسمك الشخصي هو undefined
// اسمك العائلي هو undefined

جملة إرجاع Return statement

يمكن أن تحتوي الدوال على جملة إرجاع تتكوَّن من الكلمة المفتاحية return متبوعة بقيمة.

function functionName () {
  return 'some-value'
}

عندما يجد مفسّر جافاسكريبت هذه الجملة فإنه يتوقّف عن تنفيذ التعليمات الموالية في الدالة ويُرجع قيمة (يمرّر القيمة المعنية إلى الشفرة التي استدعت الدالة):

function get2 () {
  return 2
  console.log('blah') // لن تُنفذ هذه التعليمة
}

const results = get2()
console.log(results) // تُطبع القيمة 2، وهي القيمة المُرجَعة من الدالة
// ملحوظة: لن تُطبَع القيمة 'blah'

إن كانت الكلمة المفتاحية return متبوعة بعبارة بدلا من قيمة حرفية فإن مفسّر جافاسكريبت يحدّد نتيجة تنفيذ العبارة ثم يُرجِع القيمة الناتجة.

تذكّر أن القيم التي يمكن لجافاسكريبت تمريرها هي إما أنواع أصلية (مثل سلاسل المحارف، الأعداد والقيم المنطقية) أو كائنات Objects (دوالّ، مصفوفات وكائنات). كلّ ما عدا ذلك يجب تقويمه (معرفة قيمته) قبل التمرير إلى الشفرة التي استُدعِيت فيها الدالة.

تسلسل تنفيذ التعليمات عند استدعاء الدوال

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

function add2 (num) {
  return num + 2
}

const number = add2(8)
console.log(number) // تطبع العدد 10

أولا وقبل كل شيء، نحتاج إلى تعريف الدالة قبل أن نتمكّن من استخدامها. يرى مفسّر جافاسكريبت في السطر الأول الكلمة المفتاحية function فيعرف أن الكلمة التي تليها، أي add2 هي اسم الدالة. بعد تعرّف المفسّر على اسم الدالة يتجاوز الشفرة الموجودة بين معكوفين التي تلي الاسم، لأنه حتى الآن لم يُطلب منه تنفيذ الدالة.

في السطر التالي يجد المفسّر أننا عرّفنا متغيّرا ذا قيمة ثابتة اسمه number وأسندنا له القيمة add2(8). بما أن الطرف الموجود على يمين علامة الإسناد = هو دالة، فإن جافاسكريبت سيحتاج إلى تنفيذ الدالة قبل إسناد قيمتها إلى المتغيّر. يعيّن المفسّر القيمة 8 لتكون معطى للمعامل num في الدالة ويبدأ بتنفيذ الدالة.

عند الدخول إلى كتلة الدالة (الشفرة بين قوسين معكوفين بعد اسم الدالة) يجد المفسّر أمامه الكلمة المفتاحية return متبوعة بعبارة num + 2، فيعرف أنه سيحتاج إلى معرفة نتيجة العبارة قبل الخروج من الدالة. بما أن قيمة num هي 8 فإن num + 2 يجب أن تساوي 10.

عرف المفسّر الآن قيمة العبارة num + 2 ويمكنه بالتالي إرجاع القيمة المُتحصَّل عليها إلى الشفرة التي استدعت الدالة. فيضع القيمة المرجعة مكان الدالة فتُصبح 10 مكان add2(8). يُنشئ المفسّر، بعد اكتمال تنفيذ الطرف الأيمن من عملية إسناد المتغيّر والحصول على نتيجتها، متغيّرا بالاسم المذكور number ويعطيه القيمة 10. هكذا يُقرأ تسلسل تنفيذ التعليمات في الدوال.

رفع الدوال Hoisting

تُنقَل الدوال تلقائيا عند تعريفها بالطريقة التي رأيناها سابقا إلى أعلى الشفرة البرمجية. بمعنى أن طريقتيْ التعريف والاستخدام التاليّتيْن متكافئتان تماما:

function sayHello () {
  console.log('Hello world!')
}
sayHello()

// تُحوّل الشفرة التالية عند التنفيذ تلقائياإلى الشفرة أعلاه
sayHello()
function sayHello () {
  console.log('Hello world!')
}

قد يؤدّي الرفع التلقائي للدوال إلى الإرباك؛ لذا من المناسب تعريف الدوال دائما قبل استخدامها.

تعريف الدوال بعبارات الدوال Function expressions

توجد طريقة ثانية لتعريف الدوال، وهي عبارات الدوال. يُعرَّف في هذه الحالة متغيّر ويُسنَد إلى دالة غير مسمّاة (دالة مجهولة الاسم Anonymous funvtion)

const sayHello = function () {
  console.log('This is declared with a function expression!')
}

ينبغي الانتباه إلى أن الدوال المُعرَّفة بعبارات لا تُنقَل تلقائيا إلى أعلى الشفرة. تُنتج الشفرة التالية خطأ:

sayHello () // Error, sayHello is not defined
const sayHello = function () {
  console.log('this is a function!')
}

تُستخدَم الدوال المُعرَّفة بعبارات كثيرا في توابع الكائنات Object methods وفي الدوالّ السهمية Arrow functions.

خاتمة

الدالة هي كتلة من التعليمات البرمجية تنفَّذ وفق ترتيب محدَّد على منوال: خذ سطلا فارغا، اذهب إلى البئر، اسحب الماء ثم عُد إلى المنزل.

تُستدعى الدالة بإضافة قوسين () بعد اسمها. يمكنك عند استدعاء الدالة إضافة معطيات جديدة بذكرها بين القوسين مفصولة بفاصلة ,.

يمكن لكلّ دالة أن تحوي جملة إرجاع تعيد قيمة إلى الشفرة التي استُدعِيت منها.

يُفضَّل دائما تعريف الدوال قبل استخدامها.

ترجمة - بتصرّف - للمقال Understanding JavaScript Functions لصاحبه Zell Liew.



1 شخص أعجب بهذا


تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن