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

تجربتك اﻷولى مع جافا سكريبت


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

بعد أن اطلعنا في مقال سابق على مفهوم جافا سكريبت وما يمكنها فعله، سنتابع في مقالنا هذا فكرة إنشاء تطبيق بسيط باستخدام جافا سكربت من خلال جولة إرشادية عملية نبني من خلالها تطبيق "خمّن الرقم Guess the number" خطوةً بخطوة. عليك قبل البدء بقراءة هذا المقال أن تٌلّم بأساسيات العمل على الحاسوب وأساسيات HTML و CSS وكذلك فهم طبيعة جافا سكريبت.

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

ملاحظة: إن الكثير من ميزات شيفرة جافا سكريبت هي نفسها تقريبًا في لغات البرمجة اﻷخرى مثل الدوال functions والحلقات loops وغيرها. فقد تبدو صياغة الشيفرة مختلفة لكن المفهوم يبقى ذاته.

فكّر مثل مبرمج

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

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

تطبيق -خمّن الرقم Guess the number-

نعرض في هذا التطبيق كيفية بناء لعبة بسيطة كما في المثال الحي التالي:

حاول أن تجرّب اللعبة وتعتاد عليها قبل أن نتابع، ثم لنتخيل أن مديرك قد أعطاك الوصف الموجز التالي للعبة كي تبنيها:

اقتباس

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

بعد الاطلاع على الموجز السابق، لا بد أولًا من تقسيم العملية إلى مهام أصغر قابلة للتنفيذ إستنادًا إلى عقلية المبرمج قدر اﻹمكان:

  1. توليد رقم عشوائي بين 1 و 100.
  2. تسجيل رقم المحاولة التي وصلها اللاعب ابتداءً من 1.
  3. إعطاء اللاعب طريقة ليسجًل العدد الذي يخمّنه.
  4. تسجيل العدد الذي خمّنه اللاعب وعرضه في مكان ما كي يرى محاولاته السابقة.
  5. التحقق من صحة التخمين.
  6. إن كان التخمين صحيحًا:
    1. عرض رسالة تهنئة.
    2. منع اللاعب من إدخال أية تخمينات أخرى (لأن ذلك يسيء إلى اللعبة).
    3. عرض آلية تتيح للاعب اللعب مجددًا.
  7. إن كان التخمين خاطئًا:
    1. إخبار اللاعب أن تخمينه خاطئ وإن كان التخمين قريبًا جدًا أو بعيدًا جدًا.
    2. السماح للاعب بإدخال تخمين جديد.
    3. زيادة عدّاد المحاولات بمقدار 1.
  8. إن كان التخمين خاطئًا وتجاوز اللاعب عدد المحاولات المتاحة:
    1. إبلاغ اللاعب بانتهاء اللعبة.
    2. منع اللاعب من إدخال أية تخمينات أخرى (لأن ذلك يسيء إلى اللعبة).
    3. عرض آلية تتيح للاعب اللعب مجددًا.
  9. التأكد عند إعادة اللعبة أن منطق اللعبة وواجهة المستخدم قد عادا إلى الوضع اﻷصلي، ثم العودة إلى الخطوة 1.

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

اﻹعدادات اﻷساسية

لنبدأ العمل على كتابة الشيفرة البرمجية للعبة تخمين الأرقام والتي ستعمل كما موضح في الصورة التالية.

لعبة تخمين أرقام باستخدام جافا سكريبت.PNG

تحتاج في البداية لتحضير نسخة محلية خاصة بك من الملف number-guessing-game-start.html كما تستيطع أن تختبره مباشرة ضمن المستودع المخصص له على جيت-هب. افتح الملف ضمن المتصفح وضمن المحرر النصي. سترى للوهلة الأولى ترويسة بسيطة وفقرة نصية توضح التعليمات ونموذج لإدخال التخمين، لكن التطبيق لن يعمل حاليًا.

سنضع كل شيفرة اللعبة ضمن العنصر <script> في نهاية شيفرة HTML:

<script>
  // Your JavaScript goes here
</script>

إضافة متغيرات لتخزين البيانات

أضف بداية الأسطر التالية ضمن العنصر <script>:

let randomNumber = Math.floor(Math.random() * 100) + 1;

const guesses = document.querySelector(".guesses");
const lastResult = document.querySelector(".lastResult");
const lowOrHi = document.querySelector(".lowOrHi");

const guessSubmit = document.querySelector(".guessSubmit");
const guessField = document.querySelector(".guessField");

let guessCount = 1;
let resetButton;

يهيئ هذا القسم من الشيفرة المتغيرات والثوابت التي نحتاجها لتخزين البيانات اللازمة لبرنامجنا. تُعرّف المتغيرات variables مبدئيًا بأنها أسماء لقيم مثل اﻷعداد أو النصوص. ويمكنك إنشاء متغير باستخدام التعليمة let يليها اسم المتغير. وتُعرّف الثوابت constant بأنها أسماء لقيم أيضًا لكن لا يمكن تغيير هذه القيم بمجرد أن نهيئها. نستخدم في حالتنا الثوابت لتخزين مراجع إلى عناصر من واجهة المستخدم. وقد يتغير النص ضمن تلك العناصر لكن الثوابت تشير دائمًا إلى العنصر نفسه الذي ضُبطت عليه في البداية. يمكن إنشاء الثابت باستخدام التعليمة const يليها اسم الثابت. يمكن إسناد قيمة إلى الثابت أو المتغير باستخدام الإشارة (=) تليها القيمة التي تريد.

في مثالنا:

  • يُسند إلى المتغير اﻷول randomNumber عدد عشوائي بين 1 و 100 يُحسب من خلال خوارزمية رياضية.
  • أنشئت الثوابت الثلاث اﻷولى لتخزين مراجع إلى المقاطع النصية الخاصة بالنتائج في شيفرة HTML وتستخدم ﻹدراج نصوص ضمن هذه الفقرات برمجيًا، ولاحظ أنها ضمن عنصر <div>والذي يُستخدم لاختيار المقاطع الثلاث لتصفيرها (إعادتها إلى وضعها اﻷصلي) لاحقًا عن إعادة اللعبة إلى وضعها اﻷصلي.
  <div class="resultParas">
    <p class="guesses"></p>
    <p class="lastResult"></p>
    <p class="lowOrHi"></p>
  </div>
  • يُخّزن الثابتان التاليان مرجع إلى عنصر اﻹدخال النصي في النموذج وإلى زر اﻹرسال وتُستخدمان للتحكم بإرسال العدد الذي يُخمنه اللاعب.
  <label for="guessField">Enter a guess: </label>
  <input type="number" id="guessField" class="guessField" />
  <input type="submit" value="Submit guess" class="guessSubmit" />
  • يٌخزّن المتغيران اﻷخيران القيمة 1 لعدد محاولات اللعب (ويُستخدم لتتبع عدد المحاولات التي قام بها اللاعب) ومرجعًا إلى زر إعادة الضبط الذي لا يظهر حاليًا (لكنه سيظهر لاحقًا). ملاحظة: سنتعلم أكثر عن المتغيرات والثوابت لاحقًا في سلسلة المقالات هذه عن جافا سكريبت.

الدوال

أضف تاليًا الشيفرة التالية تحت الشيفرة السابقة:

function checkGuess() {
  alert("I am a placeholder");
}

الدوال هي كتل من الشيفرة يمكن استخدامها مجددًا، إذ يمكن كتابتها مرة واحدة وتنفيذها مرارًا وتكرارًا موفرين عناء كتابة الشيفرة من جديد، وهذا أمر غاية في اﻷهمية.وهنالك عدد من الطرق في تعريف الدوال لكننا سنركز الآن على نوع بسيط. نستخدم في مثالنا الكلمة المفتاحية function متبوعةً باسم الدالة وبعدها قوسين معقوصين{}. نضع الشيفرة التي تنفذها الدالة عند استدعائها داخل القوسين المعقوصين. وعندما نريد تنفيذ الشيفرة، تكتب اسم الدالة يليها قوسين () لنجرب ذلك اﻵن، احفظ التغييرات التي أجريتها على الملف وحدّث الصفحة ضمن المتصفح. انتقل بعد ذلك إلى (طرفية جافا سكريبت ضمن أدوات مطوري ويب ثم أدخل السطر التالي:

checkGuess();

من المفترض أن ترى بعد الضغط على المفتاح Enter/Return رسالة تنبيه نصها I am a placeholder، ﻷننا عرفنا دالة في شيفرتنا تعيد هذه الرسالة كلما استدعيناها. ملاحظة: سنتعلم أكثر عن الدوال لاحقًا في سلسلة المقالات هذه.

العوامل

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

العامل اسمه مثال
+ الجمع 6 + 9
- الطرح 20 - 15
* الضرب 3 * 7
/ القسمة 10 / 5

هنالك أيضًا بعض العوامل المختصرة تُدعى عوامل اﻹسناد المركّبة compound assignment operators، فإن أردت مثلًا إضافة عدد جديد إلى عدد موجود وإعادة النتيجة، إليك الطريقة:

let number1 = 1;
number1 += 2;

وهذا مشابه لعمل الشيفرة:

let number2 = 1;
number2 = number2 + 2;

وعند تنفيذ اختبارات نتيجتها (صحيح أو خاطئ) وذلك ضمن العبارات الشرطية (سنراها لاحقًا) نستخدم عوامل الموازنة comparison operators مثل:

العامل الاسم مثال
=== مساواة تامة (هل يساويه تمامًا؟) 5===2+4 // خاطئ، chris===pop// خاطئ، 5===2+3 // صحيح، 2==='2' // خاطئ موازنة رقم بنص
==! لا مساواة تامة (هل هما غير متساويين؟) 5==!2+4 // صحيح، chris!==pop// صحيح، 5==! 2+3 // خاطئ، 2==!'2' // صحيح موازنة رقم بنص
< أقل من 10>6 // صحيح، 10>20 //خاطئ
> أكبر من 10<6 // خاطئ، 10<20 //صحيح

السلاسل النصية

تستخدم السلاسل النصية لتمثيل النصوص، وقد رأينا سابقًا متغير نصي في الشيفرة "I am a placeholder":

function checkGuess() {
  alert("I am a placeholder");
}

يمكن التصريح عن سلسلة نصية باستخدام إشارتي التنصيص المزدوجتين (" ") أو المفردتين (' ')، لكن ينبغي عليك استخدام أحد اﻷسلوبين من بداية السلسلة إلى نهايتها فلا يمكن أن تكتب مثلًا" "I am a placeholder'. باﻹمكان أيضًا تعريف السلسلة النصية بين علامتي اقتباس مائلتين (``) وتُدعى السلاسل المعرّفة بهذا الشكل بالقوالب المفسّرة template literals التي تحمل بعض الخاصيات المميزة وتحديدًا إمكانية وضع متغيرات أخرى أو تعابير برمجية ضمن السلسلة النصية لتتحول قيمها إلى جزء من النص:

const name = "Mahalia";

const greeting = `Hello ${name}`;

يمنحك هذا اﻷمر أسلوبًا لضم السلاسل النصية معًا.

العبارات الشرطية

بالعودة إلى الدالة ()ckeckGuess نجد أنه من المنطقي ألا تكون وظيفتها طباعة رسالة فقط، بل من المفترض أن تتحقق من صحة العدد الذي يخمّنه اللاعب وتعيد الجواب الملائم. لنستبدل اﻵن بالشيفرة التالية ما كان موجودًا ضمن الدالة ()ckeckGuess:

function checkGuess() {
  const userGuess = Number(guessField.value);
  if (guessCount === 1) {
    guesses.textContent = "Previous guesses:";
  }
  guesses.textContent = `${guesses.textContent} ${userGuess}`;

  if (userGuess === randomNumber) {
    lastResult.textContent = "Congratulations! You got it right!";
    lastResult.style.backgroundColor = "green";
    lowOrHi.textContent = "";
    setGameOver();
  } else if (guessCount === 10) {
    lastResult.textContent = "!!!GAME OVER!!!";
    lowOrHi.textContent = "";
    setGameOver();
  } else {
    lastResult.textContent = "Wrong!";
    lastResult.style.backgroundColor = "red";
    if (userGuess < randomNumber) {
      lowOrHi.textContent = "Last guess was too low!";
    } else if (userGuess > randomNumber) {
      lowOrHi.textContent = "Last guess was too high!";
    }
  }

  guessCount++;
  guessField.value = "";
  guessField.focus();
}

ما وضعناه كمية كبيرة من الشيفرة بالفعل، لكن سنمر على كل قسم منها ونشرحه:

  • يعرّف السطر اﻷول متغيرًا يُدعى userGuess وتُسند إليه القيمة التي أُدخلت ضمن المربع النصي في النموذج. نمرر بعد ذلك هذه القيمة إلى الدالة ()Number المدمجة في جافا سكريبت وذلك للتأكد أن هذه القيمة عدد بالفعل. وطالما أننا لن نغيّر هذا العدد فقد قررنا أن يكون ثابتًا const.
  • نواجه بعد ذلك أول كتلة شرطية، وتُستخدم الكتل الشرطية لتنفيذ الشيفرة انتقائيًا إن تحقق شرط معين أو لم يتحقق. قد تبدو العبارة الشرطية شبيهة بالدالة لكنه ليست كذلك. تبدأ أبسط أشكال الكتل الشرطية بالكلمة المحجوزة if يليها بعض اﻷقواس ثم بعض اﻷقواس المعقوصة. يوضع الشرط أو الاختبار بين اﻷقواس العادية، فإن أعاد تنفيذ الشرط النتيجة true تُنفَّذ الشيفرة الموجودة ضمن اﻷقواس المعقوصة، وإن لم يكن اﻷمر كذلك، فلن تنفَّذ تلك الشيفرة وينتقل التنفيذ إلى القسم اﻵخر من الشيفرة. يختبر الشرط فيما لو كانت قيمة المتغيّر guessCount مساويًا للقيمة 1 (أي إذا كانت هذه المحاولة اﻷولى للاعب أم لا):
  guessCount === 1;

إن تحقق ذلك، نجعل النص المحتوى ضمن الفقرة النصية guesses مساويًا Previous guesses، وإن لم يتحقق لا نفعل ذلك.

  • نستخدم بعد ذلك قالبًا مفسّرًا لضم قيمة المتغّير userGuess إلى نهاية النص في الفقرة النصية guesses مع وجود مسافة فارغة بينهما.
  • تُنفِّذ الشيفرة التالية عدة اختبارات:
  • تتحق العبارة الشرطية اﻷولى {}()if إن كان التخمين الذي أدخله اللاعب مساويًا قيمة المتغيّر randomNumber الذي ضُبطت قيمته في بداية الشيفرة. فإن كان تخمين اللاعب صحيحًا، ربح اللعبة، لهذا نعرض رسالة تهنئة بلون أخضر ونمسح محتويات صندوق المعلومات الذي يشير إلى بعد أوقرب التخمين الخاطئ عن القيمة الصحيحة، ثم تُنفَّذ الدالة ()setGameOver التي سنناقشها لاحقًا.
  • نربط بعد ذلك اختبارًا آخر في نهاية اﻷول من خلال البنية {}()else if والتي تتحقق إن كان الدور الذي لعبه اللاعب هو آخر دور له. فإن كان كذلك، يكرر ما فعلناه في الكتلة السابقة لكن مع رسالة تشير إلى نهاية اللعبة بدلًا من رسالة التهنئة.
  • أما الكتلة اﻷخيرة التي نربطها بسابقتها فهي الكتلة {}else التي تضم شيفرة تُنفَّذ فقط إن فشل الاختباران في الكتلتين السابقتين (أي اللاعب لم يخمن العدد، ,ولم ينهي جميع محاولاته). نخبره في هذه الحالة أن تخمينه خاطئ ثم ننفذ اختبارًا آخر يتحقق إن كان تخمينه أكبر بكثير أو أقل بكثير من العدد الصحيح ثم نعرض رسالة أخرى بطريقة مناسبة ﻹخبار اللاعب بذلك.
  • تحضر اﻷسطر الثلاث اﻷخيرة من الدالة (من 26 إلى 28) إرسال لتخمين التالي. إذ تضيف 1 إلى المتغير guessCount كي يستنفذ اللاعب دورًا جديدًا
    (العامل ++ هو عامل يزيد قيمة المتغير بمقدار 1). وتفرّغ قيمة المربع النصي في النموذج وتعطيه تركيز الدخل مجددًا، وبهذا يصبح اللاعب جاهزًا ﻹدخال التخمين التالي.

اﻷحداث

ما فعلنا حتى اﻵن هو إنجاز الدالة لكنها لن تفعل شيئًا لأننا لم نستدعها بعد. ومن المنطقي أن نستدعي هذه الدالة عند النقر على زر "Submit guess"، ولإنجاز ذلك، نحتاج إلى ما يُدعى حدثًا event. فاﻷحداث هي أشياء تحدث في المتصفح مثل نقر زر أو تحميل صفحة أو تشغيل فيديو وغيرها. ولكي ينفّذ المتصفح كتلة من الشيفرة كاستجابة لحدث ما نحتاج إلى مترصّد أحداث event listener يراقب أحداث معينة ويستدعي معالج أحداث event handler مناسب، والمعالج هو كتل من الشيفرة تعمل استجابةً لوقوع حدث في المتصفح. أضف السطر التالي تحت الدالة ()checkGuess:

guessSubmit.addEventListener("click", checkGuess);

أضفنا هنا مترصّد أحداث إلى الزر، وهو تابع يأخذ قيمتين (تُدعيان وسيطين arguments)، اﻷول هو نوع الحدث الذي نترصده فهو حدث (النقر click) وله قيمة نصية، والثاني هو الشيفرة التي تُنفَّذ عند وقوع الحدث وهي في حالتنا الدالة ()checkGuess. ولاحظ أنه لا حاجة لوضع القوسين عند كتابة الدالة كوسيط لمترصد الحدث ()addEventListener جرّب حفظ التغييرات على الملف ثم إعادة تحميل الصفحة في متصفحك وسيعمل التطبيق إلى حد معين. وما سيحدث أنه لو خمّنت العدد الصحيح أو أنهيت كل محاولاتك ستنهار اللعبة لأننا لم نعرّف بعد الدالة ()setGameOver التي من المفترض أن تُستدعى عند نهاية اللعبة. لهذا سنضيف الشيفرة الناقصة ﻹكمال اللعبة

إنهاء جميع وظائف اللعبة

لنضف اﻵن الدالة ()setGameOver إلى أسفل الشيفرة التي كتبتها حتى اﻵن ثم نشرح ما تفعله:

function setGameOver() {
  guessField.disabled = true;
  guessSubmit.disabled = true;
  resetButton = document.createElement("button");
  resetButton.textContent = "Start new game";
  document.body.append(resetButton);
  resetButton.addEventListener("click", resetGame);
}
  • يعطّل أول سطرين عمل عنصر اﻹدخال النصي في النموذج وعمل الزر بضبط الخاصية disabled على القيمة trueلكل منهما. وهذا اﻷمر ضروري، لأن اللاعب سيتمكن من إرسال قيم تخمين أخرى رغم إنتهاء اللعبة، وسيجعل ذلك اللعبة فوضوية.
  • توّلد اﻷسطر الثلاث التالية زرًا جديدًا <button>بعنوان "Start new game" ومن ثم تضيفه إلى شيفرة HTML الموجودة.
  • يضبط السطر اﻷخير مترصّد أحداث للزر الجديد كي يترصد حدث النقر عليه ويستدعي الدالة ()resetGame. علينا اﻵن كتابة الشيفرة الخاصة بالدالة اﻷخيرة، لهذا ضع الشيفرة التالية في آخر ما كتبته:
function resetGame() {
  guessCount = 1;

  const resetParas = document.querySelectorAll(".resultParas p");
  for (const resetPara of resetParas) {
    resetPara.textContent = "";
  }

  resetButton.parentNode.removeChild(resetButton);

  guessField.disabled = false;
  guessSubmit.disabled = false;
  guessField.value = "";
  guessField.focus();

  lastResult.style.backgroundColor = "white";

  randomNumber = Math.floor(Math.random() * 100) + 1;
}

هذه الكتلة من الشيفرة طويلة نوعًا ما وتعيد كل شيء إلى وضعه اﻷصلي عند بداية اللعبة، وبالتالي يصبح اللاعب قادرًا على المتابعة من جديد، فهي:

  • تعيد قيمة المتغير guessCount إلى 1.
  • تفرّغ كل ما هو موجود في الفقرات النصية. فقد اخترنا جميع الفقرات النصية ضمن العنصر <div class="resultParas"></div> ثم تفقدنا من خلال حلقة كل فقرة وضبطنا الخاصية textContent لكل منها على' ' (سلسلة فارغة).
  • تزيل زر إعادة الضبط من الشيفرة.
  • تفعّل عناصر النموذج وتفرّغ الفقرات النصية وتعطي تركيز الدخل إلى مربع اﻹدخال النصي في النموذج كي يصبح جاهزًا لتلقي تخمين جديد من قبل اللاعب.
  • تزيل لون خلفية الفقرة النصية lastResult.
  • توّلد رقم عشوائي جديد كي لا تخمّن نفس الرقم العشوائي السابق. لقد اكتملت اللعبة اﻵن، تهانينا! وكل ما بقي لنا في هذا المقال هو الحديث عن بعض الميزات الهامة التي رأيناها في شيفرة اللعبة والتي ربما لم تدركها.

الحلقات

من أهم أجزاء الشيفرة التي كتبناها، والتي لا بد من الحديث عنها هي حلقة (for…of). فالحلقات هي مفاهيم برمجية غاية في اﻷهمية تتيح لك تنفيذ جزء من الشيفرة مرارًا وتكرارًا حتى يتحقق شرط معين. وكي نبدأ تتبع عمل الحلقات انتقل إلى طرفية جافا سكريبت في أدوات مطوري ويب، ثم أدخل الشيفرة التالية:

const fruits = ["apples", "bananas", "cherries"];
for (const fruit of fruits) {
  console.log(fruit);
}

ما الذي حدث؟ لقد طبعت الكلمات 'apples', 'bananas', 'cherries' على الشاشة كنتيجة لتنفيذ الحلقة. إذ يُنشئ السطر

 ;['const fruits = ['apples', 'bananas', 'cherries 

مصفوفة (سنتعرف عليها لاحقًا في مقال آخر) وهي مبدئيًا مجموعة من العناصر (سلاسل نصية في حالتنا). وتزوّدك الحلقة for...of بطريقة للحصول على كل عنصر من المصفوفة وتطبيق شيفرة جافا سكريبت عليه، فما يفعله السطر (for (const fruit of fruits هو التالي:

  1. الحصول على أول عناصر المصفوفة fruits.
  2. ضبط قيمة المتغيّر fruit لتكون قيمة العنصر اﻷول، ثم تنفيذ شيفرة جافا سكريبت الموجودة داخل القوسين {}.
  3. الحصول على العنصر التالي من المصفوفة fruits.

في هذه الحالة، تطبع الشيفرة قيمة المتغيّر fruit على الشاشة. لنلق نظرة اﻵن على الحلقة الموجودة في لعبة "خمّن الرقم" وتحديدًا ضمن الدالة ()resetGame:

const resetParas = document.querySelectorAll(".resultParas p");
for (const resetPara of resetParas) {
  resetPara.textContent = "";
}

توّلد هذه الشيفرة متغيّرًا يضم قائمة بجميع الفقرات النصية الموجودة ضمن العنصر <div class="resultParas"> باستخدام التابع ()querySelectorAll ومن ثم يتفقد كل فقرة باستخدام حلقة ويزيل المحتوى النصي لها. وتجدر الملاحظة أن ثوابت مثل resetParas يمكن إزالة المحتوى النصي لها.

مناقشة سريع لمفهوم الكائن Object في جافا سكريبت

سنضيف تحسينًا أخيرًا إلى اللعبة قبل الدخول في هذا النقاش وهو سطر يجب وضعه تحت السطر ;let resetButton بالقرب من بداية شيفرة جافا سكريبت ثم نحفظ التغيرات:

guessField.focus();

يستخدم هذا السطر التابع ()focus الذي يجعل مؤشر الدخل ضمن عنصر اﻹدخال النصي <input> حالما تُحمّّل الصفحة، وهكذا يصبح اللاعب جاهزًا لكتابة تخمينه مباشرة دون الحاجة إلى النقر داخل مربع اﻹدخال النصي. صحيح أنها إضافة صغيرة لكنها تحسن استخدام اللعبة وتمنح اللاعب فكرة عما سيفعله تاليًا حتى يبدأ اللعب.

لنحلل ما يجري هنا بمزيد من التفصيل. إذ نتعامل غالبًا في جافا سكريبت مع الكائنات objects، والكائن هو مجموعة مترابطة من الوظائف المخزّنة في شيء واحد. بإمكانك بالطبع إنشاء كائنات خاصة بك، لكن اﻷمر متقدم قليلًا ولن نغطيه في مقالنا. أما ما نناقشه اﻵن باختصار فهي الكائنات المدمجة مع اللغة والتي يتضمنها متصفحك وتسمح لك بتنفيذ العديد من الأمور المفيدة. في هذه الحالة الخاصة، أنشأنا ثابتًا يخزّن مرجعًا إلى عنصر اﻹدخال النصي الموجود في نموذج HTML، وستجد السطر التالي ضمن التصريحات في بداية الشيفرة:

const guessField = document.querySelector(".guessField");

وللحصول على هذا المرجع، استخدمنا التابع ()querySelector العائد إلى الكائن document. ويأخذ هذا التابع معلومة واحدة وهي محدد CSS الذي يُستخدم ﻹنتقاء العنصر الذي تريد إنشاء مرجع إليه.

ولأن الثابت guessField يحتوي مرجعًا إلى العنصر <input>، فلديه القدرة اﻵن على الوصول إلى خصائصه (تُخزَّن المتغيرات أساسًا ضمن كائنات، ولا يمكن تغيير قيم بعضها) وتوابعه (وهي أساسًا دوال مخزّنة ضمنه). ومن أحد توابع عنصر اﻹدخال النصي نجد ()focus لهذا يمكننا استخدام السطر التالي لنقل تركيز الدخل إلى هذا العنصر:

guessField.focus();

لا يمكن استخدام التابع ()focus على المتغيرات التي لا تضم مراجعًا إلى عناصر، فالثابت guesses مثلًا يضم مرجعًا إلى العنصر <p> والمتغير guessCount يضم عددًا.

التعامل مع كائنات المتصفح

لنعمل قليلًا مع بعض كائنات المتصفح:

  1. افتح ملف اللعبة أولًا ضمن المتصفح.
  2. افتح أدوات مطوري ويب في متصفحك (من زر القائمة>أدوات إضافية>أدوات مطوري ويب "في متصفح فايرفكس"). وتأكد من وصولك إلى طرفية جافا سكريبت.
  3. اكتب في الطرفية guessField وستعرض لك حينها أن هذا المتغيّر يضم العنصر <input>، وستلاحظ أيضًا أن الطرفية تعرض لك تلقائيًا أسماء جميع الكائنات الموجودة ضمن بيئة التنفيذ بما في ذلك متغيّراتك التي صرحت عنها.
  4. اكتب اﻵن مايلي:
   guessField.value = 2;

تمثل الخاصية value القيمة الحالية المُدخلة إلى مربع النص، وسترى أن تنفيذ اﻷمر السابق يغيّر النص الموجود في مربع النص.

  1. جرّب أن تكتب guesses في الطرفية ثم اضغط المفتاح "Enter" وسترى أن هذا المتغير يتضمن العنصر <p>.

  2. جرّب كتابة اﻷمر التالي: guesses.value وسيعيد المتصفح القيمة undefined لأن الفقرة النصية لا تمتلك الخاصية value

  3. لتغيير النص داخل الفقرة النصية جرّب الأمر التالي: "?guesses.textContent="Where is my paragraph

  4. ولكي تجرب أشياء أخرى، اكتب اﻷسطر التالية:

   guesses.style.backgroundColor = "yellow";
   guesses.style.fontSize = "200%";
   guesses.style.padding = "10px";
   guesses.style.boxShadow = "3px 3px 6px black";

لكل عنصر في الصفحة خاصية تُدعى style تضم بحد ذاتها كائنًا له خاصيات تتضمن جميع تنسيقات CSS السطرية المطبقة على العنصر. ويسمح لنا ذلك ضبط تنسيقات جديدة للعنصر ديناميكيًا من خلال جافا سكريبت.

الخلاصة

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

ترجمة -وبتصرف- للمقال Afirst splash into JavaScript

اقرأ أيضًا


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

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

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



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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...