اذهب إلى المحتوى

بناء دوال خاصة بك في جافا سكريبت


ابراهيم الخضور

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

  1. أساسيات علوم الحاسب.
  2. أساسيات HTML.
  3. أساسيات عمل CSS
  4. أساسيات جافا سكريبت كما شرحناها في سلسلة المقالات السابقة.

تطبيق عملي: بناء دالة

سنبني في هذا التمرين دالة باسم ()displaymessage مهمتها عرض مربع رسالة على صفحة ويب، وستعمل كبديل خاص بك عن الدالة المدمجة مع المتصفح ()alert.تحدثنا عن عمل هذه الدالة سابقًا لكننا سنعيدها لتتذكر بعض التفاصيل. لهذا اكتب الشيفرة التالية في طرفية جافا سكريبت في متصفحك:

alert("This is a message");

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

ملاحظة: ينبغي أن تعمل الشيفرة ضمن جميع المتصفحات الحديثة، لكن قد يبدو التنسيق غريبًا قليلًا في المتصفحات اﻷقدم. لهذا ننصحك بتنفيذ هذا التمرين في متصفحات حديثة مثل فايرفوكس وأوبرا وكروم.

الدالة اﻷساسية

لنبدأ بتشكيل دالة أساسية مع التقيد بنفس قواعد التسمية المتبعة عند تسمية المتغيرات، فلا مشكلة في ذلك طالما أن الدوال يتبعها قوسان وبالتالي يمكن تمييزها عن المتغيرات.

  1. أنشئ نسخة خاصة بك من ملف HTM الخاص بالتمرين وستجده بسيطًا يحتوي جسمه على زر واحد ويضم أيضًا تنسيقات CSS أساسية لتنسيق صندوق الرسالة، كما ستجد العنصر <script> الذي يضم شيفرة جافا سكريبت الخاصة بالتمرين
  2. أضف الشيفرة التالية ضمن العنصر <script>:
function displayMessage() {
  ...
}

تبدأ الشيفرة بالكلمة المفتاحية function والتي تعني أننا نعرّف تابعًا يليها الاسم الذي نريد تسمية الدالة به يليه زوج من الأقواس وزوج من اﻷقواس المعقوصة. ونضع أية معاملات نريد نعطيها للدالة داخل القوسين العاديين، بينما نضع الشيفرة التي تنفذها الدالة بين القوسين المعقوصين.

  1. أضف أخيرًا الشيفرة التالية ضمن القوسين المعقوصين:
const body = document.body;

const panel = document.createElement("div");
panel.setAttribute("class", "msgBox");
body.appendChild(panel);

const msg = document.createElement("p");
msg.textContent = "This is a message box";
panel.appendChild(msg);

const closeBtn = document.createElement("button");
closeBtn.textContent = "x";
panel.appendChild(closeBtn);

closeBtn.addEventListener("click", () =>
  panel.parentNode.removeChild(panel),
);

يختار السطر الأول من الشيفرة العنصر <body> باستخدام الواجهة البرمجية لشجرة DOM للحصول على الخاصية body للكائن document الذي يمثل مستند HTML بالكامل ثم يسند قيمته لثابت يُدعى body:

const body = document.body;

يستخدم القسم الثاني أحد دوال الواجهة البرمجية ()document.createElement ﻹنشاء عنصر <div> ثم يخزّن مرجعًا إليه ضمن ثابت يُدعى panel. سيمثّل هذا العنصر الحاوية الخارجية لصندوق الرسائل.

نستخدم بعد ذلك دالة أخرى ()Element.setAtrtribute لضبط السمة class العائدة للوحة صندوق الرسائل على msgbox كي يسهل تنسيق العنصر. فلو ألقيت نظرة على تنسيقات الصفحة ستجد أنها تحتوي على الصنف msgbox. لتنسيق صندوق الرسائل ومحتواه.

نستدعي أخيرًا الدالة ()Node.appendChild للثابت body الذي عرَفناه سابقًا والتي تضع عنصرًا ضمن آخر كابن له. وخصصنا العنصر <div> ليكون ابنًا للعنصر <body> والسبب في ذلك ألا يظهر العنصر الذي ننشئه في مكانه الافتراضي في الصفحة بل نريد وضعه في مكان نخصصه له.

const panel = document.createElement("div");
panel.setAttribute("class", "msgBox");
body.appendChild(panel);

نستخدم تاليًا الدالتين ()createElement و ()appendChilde اللتان رأينا عملهما سابقًا في إنشاء عنصري فقرة نصية <p> والحاقهما في الصفحة كابنين للعنصر <div>. وبعدها نستخدم الخاصية Node.textContent والتي تمثل المحتوى النصي للفقرة لوضع الرسالة المطلوبة ضمن الفقرة النصية وإشارة "x" كعنوان للزر لتعكس وظيفته وهي إغلاق صندوق الرسائل.

const msg = document.createElement("p");
msg.textContent = "This is a message box";
panel.appendChild(msg);

const closeBtn = document.createElement("button");
closeBtn.textContent = "x";
panel.appendChild(closeBtn);

ثم نستدعي في النهاية الدالة ()addEveentListener ﻹضافة دالة (دالة سهمية غير مسماة) تُستدعى عندما ينقر المستخدم على الزر ومهمتها حذف العنصر الذي يمثل صندوق الرسائل بأكمله من الصفحة. يُمرر للتابع ()addEveentListener الذي يمكن أن يستخدمه أي عنصر في الصفحة دالة أخرى واسم الحدث الذي ينبغي ترصده وهو في حالتنا "click"، أي ستُنفّذ الدالة عندما ينقر المستخدم على الزر ( سنتحدث بتفصيل أكثر عن اﻷحداث في مقال "مدخل إلى اﻹحداث في جافا سكريبت. أما الدالة التي نستخدمها عند وقوع الحدث فتضم دالة أخرى من دوال الواجهة البرمجية لشجرة المستند DOM وهي ()Node.removeChild التي تزيل ابنًا محددًا من أبناء العنصر وهو في حالتنا العنصر <div>:

closeBtn.addEventListener("click", () => panel.parentNode.removeChild(panel));

تعرض الشيفرة السابقة طريقة إنشاء عناصر HTML برمجيًا وستضيف شيفرتنا السابقة إلى الصفحة مايلي:

<div class="msgBox">
  <p>This is a message box</p>
  <button>x</button>
</div>

لا تقلق إن لم تتذكر تمامًا كيف تعمل الشيفرة السابقة، فكل ما نهتم له اﻵن هو هيكلية الدالة التي أنشأناها واستخدامها.

استدعاء الدالة

عرفّنا اﻵن الدالة التي نريدها ضمن العنصر <script> بالشكل الصحيح، لكنها لن تفعل شيئًا بنفسها.

  1. جرّب أن تضيف السطر التالي تحت الدالة في الشيفرة:
displayMessage();

يستدعي هذا السطر الدالة وينفذها مباشرة. فعندما تحفظ التغييرات وتعيد تحميل الصفحة، يعرض المتصفح الشيفرة في الصفحة مباشرة ولمرة واحدة، لأننا استدعيناها مرة واحدة.

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

  2. احذف السطر اﻷخير الذي أضفته إلى الشيفرة.

  3. ما سنفعله تاليًا هو اختيار الزر ثم حفظ مرجع إليه ضمن ثابت، لهذا أَضف الشيفرة التالية أعلى تعريف الدالة:

const btn = document.querySelector("button");
  1. أضف السطر التالي بعد السطر السابق:
btn.addEventListener("click", displayMessage);

وعلى غرار ما فعلناه للتعامل مع حدث النقر على زر اﻹغلاق closeBtn نستدعي في هذا السطر الشيفرة كاستجابة لحدث النقر على الزر، لكن بدلًا من استدعاء دالة غير مسماة سنستدعي الدالة التي أنشأناها ()displayMessage باسمها.

  1. احفظ التغييرات وأعد تحميل الصفحة، سترى اﻵن الرسالة فقط عندما تنقر على الزر.

قد تتسائل لماذا لم نضع القوسين بعد اسم الدالة عندما نراها كمعامل لدالة ترصد الأحداث؟ السبب هو أننا لا نريد تنفيذ الدالة دون النقر على الزر. فلو غيرت الشيفرة لتصبح على الشكل:

btn.addEventListener("click", displayMessage());

ثم حفظت التغيرات وأعدت تحميل الصفحة، ستظهر الرسالة مباشرة دون النقر على الزر.

تُدعى اﻷقواس أحيانًا وفق هذا السياق "عامل تنفيذ الدالة function invocation operator"، وتسُستخدم عندما تريد تنفيذ الدالة مباشرة ضمن نطاق العمل الحالي. بالمقابل، لا تُنفّذ الشيفرة داخل الدالة غير المسماة مباشرة، لأنها ضمن نطاق الدالة التي تترصد الحدث.

تراجع عن التغيرات السابقة إن جربت الفكرة السابقة قبل المتابعة.

تحسين الدوال باستخدام المعاملات

لا زالت الدالة بشكلها الحالي غير مفيدة، فلا نريد عرض نفس الرسالة دائمًا، لهذا سنحاول تحسين الدالة بإضافة معاملات تسمح لنا باستدعائها وفق عدة خيارات:

  1. عدّل بداية السطر اﻷول من الدالة ليصبح كالتالي:
function displayMessage(msgText, msgType) {

عندما نستدعي الدالة اﻵن، يمكننا تزويدها بمتغيرين ضمن القوسين لتحديد الرسالة التي تعرضها في صندوق الرسائل ونوع هذه الرسالة.

  1. للاستفادة من المعامل اﻷول، عدّل السطر التالي:
msg.textContent = "This is a message box";

ليصبح بالشكل:

msg.textContent = msgText;
  1. عليك اﻵن تعديل استدعاء الدالة لتضم نص الرسالة الجديد، لهذا عدّل السطر التالي:
btn.addEventListener("click", displayMessage);

ليصبح بالشكل:

btn.addEventListener("click", () =>
  displayMessage("Woo, this is a different message!"),
);

إن أردنا أن نخصص معاملات ضمن دالة نستدعيها ضمن قوسي دالة أخرى، لا يمكننا استدعائها مباشرة، ولا بد من وضعها ضمن دالة غير مسماة، وبالتالي لن تكون ضمن مجال رؤية الدالة المستدعية مباشرة زلن تُستدعى مباشرة. وهكذا لن تُستدعى الدالة حتى ينقر المستخدم على الزر.

  1. أعد تحميل الصفحة مجددًا وسترى أنها لا تزال تعمل جيدًا، ما عدا أنك تستطيع تغيير الرسالة الموجودة ضمن المعامل لتعرض رسالة مختلفة في صندوق الرسائل.

معامل أكثر تعقيدًا

بالنسبة للمعامل اﻵخر، سيتطلب اﻷمر عملًا أكثر. إذ سنجعل صندوق الرسائل يعرض أيقونة مختلفة وخلفية ذات لون مختلف وفقًا لقيمة هذا المعامل (msgType).

  1. حمّل اولاً اﻷيقونات اللازمة لهذا التمرين (أيقونة التحذير وأيقونة المحادثة) ثم خزنهما في المجلد "icons".
  2. ابحث عن تنسيقات CSS داخل الملف لأننا سنجري بعض التغييرات لعرض اﻷيقونات، ثم عدّل اتساع صندوق الرسائل من width: 200px إلى width: 242px.
  3. أضف الشيفرة التالية داخل القاعدة {} msgBox p.:
padding-left: 82px;
background-position: 25px center;
background-repeat: no-repeat;
  1. سنضيف اﻵن بعض الشيفرة إلى الدالة ()displayMessage لعرض اﻷيقونات بالشكل المطلوب. لهذا ضع الشيفرة التالية داخل القوسين المعقوصين للدالة:
if (msgType === "warning") {
  msg.style.backgroundImage = "url(icons/warning.png)";
  panel.style.backgroundColor = "red";
} else if (msgType === "chat") {
  msg.style.backgroundImage = "url(icons/chat.png)";
  panel.style.backgroundColor = "aqua";
} else {
  msg.style.paddingLeft = "20px";
}

إن كانت قيمة العامل msgBox  هي warning ستُعرض أيقونة التحذير وتصبح لون خلفية صندوق الرسائل أحمر، وإن كانت قيمته chat ستُعرض أيقونة المحادثة ويصبح لون الخلفية أزرق مائي. إما إن لم تُضبط قيمة المعامل msgType أو أسندت إليه قيمة غير محددة، ستُنفَّذ الشيفرة داخل {}else وستأخذ الفقرة النصية الحاشية الافتراضية ولن تظهر اﻷيقونة ولن يُضبط لون الخلفية، وبهذا يكون هذا المعامل اختياريًا.

  1. لنجرّب اﻵن الشكل المعدّل للدالة ()displayMessage ونغيّر طريقة الاستدعاء من الشكل:
displayMessage("Woo, this is a different message!");

لتصبح كالتالي:

displayMessage("Your inbox is almost full — delete some mails", "warning");
displayMessage("Brian: Hi there, how are you today?", "chat");

لاحظ فائدة المعاملات في تحسين طريقة عمل الدوال.

ملاحظة: إن لم تعمل الشيفرة أو واجهتك المشاكل، بإمكانك موازنة شيفرتك مع الشيفرة الجاهزة على جت-هب (أو تجريها مباشرة) أو طرح أية أسئلة في قسم التعليقات أسفل المقال أو في قسم الأسئلة والأجوبة في أكاديمية حسوب.

الخلاصة

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

ترجمة -وبتصرف- للمقال: Build your own function

اقرأ أيضًا


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

أفضل التعليقات

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



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...