محمد قتيبة شيخانيأبني. أستكشف. أشارك

11من 18

تطوير الويب

لغة JavaScript: بثّ الحياة في صفحتك

بنيت الهيكل العظميّ بـHTML، وكسوته بـCSS، فصار مشروعك جميلًا لكنه ثابتٌ صامتٌ كتمثال. آن أن تبثّ فيه الحياة، وأن تمنحه «جهازًا عصبيًّا وعقلًا» يستجيب للمستخدم. هذا دور JavaScript: اللغة التي تحوّل صفحات الويب من مستنداتٍ ثابتةٍ إلى تطبيقاتٍ تفاعلية. وفي هذا الدليل تأخذ مشروعك ذاته وتضيف إليه أوّل وظيفةٍ ديناميكية.

ما لغة JavaScript؟

خلافًا لـHTML وCSS اللتين تصفان «ما» يظهر على الشاشة، فإن JavaScript لغة برمجةٍ حقيقيةٌ كاملة، تعطي المتصفّح منطقًا وتعليمات وتخبره «كيف» يتصرّف.[1] فالفرق بين اللغات الثلاث يتّضح في مثالٍ واحد: HTML يقول «هنا زرّ»، وCSS يقول «اجعله أزرق بزوايا دائرية»، وJavaScript يقول «حين ينقر المستخدم هذا الزرّ، افعل شيئًا: أظهِر رسالةً أو غيّر لون الصفحة». الأولى تصف، والأخيرة تأمر وتتفاعل.

شيفرة JavaScript لتبديل الوضع الليلي في محرّر VS Code.

ووظيفتها الأساسية التاريخية أنها تعمل داخل متصفّح المستخدم مباشرةً: حين تزور صفحةً، ينزّل متصفّحك ملفّات HTML وCSS وJavaScript، ثمّ ينفّذ «محرّك جافاسكربت» المدمج فيه الشيفرة. هذا التنفيذ «من جانب العميل» هو ما يتيح التلاعب بمحتوى الصفحة لحظيًّا، والتحقّق من صحّة النماذج وإعطاء المستخدم ملاحظةً فورية دون إرسالٍ إلى الخادم، وإنشاء الرسوم المتحركة والقوائم المنسدلة، وبناء «تطبيقات الصفحة الواحدة» (SPA) التي تحدّث محتواها دون إعادة تحميل الصفحة كلّها (مثل بريد جيميل وخرائط جوجل).

وكانت JavaScript حبيسة المتصفّح، حتى تغيّر ذلك جذريًّا سنة 2009 بظهور بيئة «Node.js»، التي تتيح تشغيل JavaScript على الخادم مباشرةً.[2] فصارت قادرةً على ما كانت تفعله لغات الخادم التقليدية (كـPHP وPython): التعامل مع قواعد البيانات، وبناء واجهات البرمجة، وإدارة الملفّات. وبهذا صارت لغة «الحزمة الكاملة» (Full-Stack)، يبني بها المطوّر الواجهة الأمامية والخلفية بلغةٍ واحدة.

شعار Node.js، بيئة تشغيل JavaScript خارج المتصفّح.

نبذة تاريخية: كيف وُلدت JavaScript

في منتصف التسعينيات اشتعلت «حرب المتصفّحات» الأولى بين Netscape Navigator وInternet Explorer. أرادت Netscape لغةً تجعل صفحاتها تفاعلية، فكلّفت المبرمج Brendan Eich بصنعها، فطوّر النسخة الأولى في عشرة أيّامٍ فقط في مايو 1995.[3] سُمّيت أوّلًا «Mocha»، ثمّ «LiveScript»، واستقرّت على «JavaScript» في محاولةٍ تسويقيةٍ للاستفادة من شهرة لغة Java الصاعدة آنذاك، رغم أن لا علاقة تقنيةً حقيقيةً بينهما. (هذا الخلط لا يزال شائعًا: Java وJavaScript لغتان مختلفتان تمامًا).

بريندان آيك، مبتكر لغة JavaScript.
بريندان آيك، الذي صنع JavaScript في عشرة أيّامٍ سنة 1995.

ولمّا أطلقت Netscape اللغة، هندستها مايكروسوفت عكسيًّا وأطلقت نسختها «JScript»، فعمّت الفوضى واضطُرّ المطوّرون إلى شيفرةٍ مختلفةٍ لكل متصفّح. ولحلّ هذا، قُدّمت اللغة إلى هيئة المعايير ECMA International لتوحيدها، فنتج معيارٌ رسميٌّ اسمه «ECMAScript».[4] ببساطة: ECMAScript هو «الوصفة» التي تحدّد كيف تعمل اللغة، وJavaScript هي تطبيق تلك الوصفة في المتصفّحات.

ظلّ تطوّر اللغة بطيئًا سنواتٍ، حتى انفجرت شعبيّتها في العقد الأخير لسببين: ظهور Node.js سنة 2009 الذي جعلها لغة حزمةٍ كاملة، وإصدار «ES6» (ECMAScript 2015)، أكبر تحديثٍ في تاريخها، الذي أضاف ميزاتٍ حديثةً مثل let وconst والدوال السهمية والأصناف. ومنذ 2015 تتلقّى اللغة تحديثاتٍ سنويةً منتظمة. واليوم هي من أشهر لغات البرمجة في العالم، تشغّل واجهات الويب كلّها تقريبًا، والخوادم عبر Node.js، وتطبيقات الجوال (عبر أدواتٍ مثل React Native)، وحتى برامج سطح المكتب (عبر Electron، الذي بُني به محرّرك VS Code نفسه). فاللغة التي وُلدت في عشرة أيّامٍ صارت تحيط بالعالم الرقميّ من أطرافه.

كيف تضيف JavaScript إلى صفحتك

كما في CSS، أفضل ممارسةٍ فصل الشيفرة في ملفٍّ خاصٍّ بامتداد .js (مثل script.js)، ثمّ ربطه بوسم <script>. لكن خلافًا لوسم <link> الخاصّ بـCSS، أفضل موضعٍ لوسم السكربت هو قبل إغلاق </body> مباشرةً:

<body>
    <!-- محتوى الصفحة -->
    <script src="script.js"></script>
</body>

ولماذا في النهاية؟ يقرأ المتصفّح الصفحة من أعلاها إلى أسفلها، كبنّاءٍ يبني من المخطّط. فإن وضعت السكربت في الرأس، فكأنك أرسلت كهربائيًّا قبل أن تُبنى الجدران: سيبحث عن عنصرٍ ليتفاعل معه (document.querySelector('button')) فلا يجده لأنه لم يُبنَ بعد، فيفشل. أمّا وضعه في نهاية الجسم فيضمن أن المتصفّح أتمّ بناء هيكل HTML كاملًا (الـDOM) قبل أن تعمل شيفرتك، فتكون كل العناصر جاهزةً للتفاعل.

التفاعل مع الصفحة عبر الـ DOM

JavaScript لا تعدّل ملفّات HTML وCSS المصدرية مباشرةً، بل تتفاعل مع النسخة الحيّة التي يبنيها المتصفّح في الذاكرة. تذكر من مقال المتصفّح أن أوّل ما يفعله المتصفّح قراءة HTML وبناء «شجرة» منظّمةٍ لكل العناصر. هذه الشجرة الحيّة هي «نموذج كائن المستند» (DOM)، وهي شجرة عائلةٍ حيّةٌ لصفحتك.[5] ولـJavaScript قدرةٌ على: إيجاد أيّ عنصرٍ (بـdocument.querySelector())، وتغيير محتواه وسماته، وتغيير مظهره بإضافة أصناف CSS أو إزالتها، وإنشاء عناصر جديدة، والاستماع لأفعال المستخدم (الأحداث). هذا التفاعل مع الـDOM هو ما يحوّل مستندًا ثابتًا إلى تطبيقٍ يستجيب لحظيًّا.

ولـJavaScript قدرةٌ أبعد من تعديل الصفحة: أن تجلب بياناتٍ من خادمٍ بعيدٍ وتعرضها دون إعادة تحميل الصفحة. حين يصلك إشعارٌ جديدٌ في موقعٍ دون أن تحدّثه، أو تظهر نتائج بحثٍ وأنت تكتب، فإن JavaScript تتحدّث في الخلفية مع «واجهة برمجة تطبيقات» (API) تطلب منها البيانات وتعرضها. هذا هو سرّ «تطبيقات الصفحة الواحدة»، وهو موضوعٌ نفرد له مقال «واجهة برمجة التطبيقات» لاحقًا في السلسلة.

أساسيات اللغة: من المتغيّرات إلى التفاعل

كل موضوعٍ ممّا يأتي عالمٌ بذاته، وهدفي هنا نظرةٌ أولى مبسّطةٌ تمنحك ما يكفي لبناء أوّل تفاعل، لا أن تتقن كل شيءٍ فورًا. وأمامك ثلاث خطوات: كيف تخزّن المعلومات، ثمّ كيف تتفاعل مع الصفحة، ثمّ كيف تنظّم أوامرك.

وقبل ذلك، تعرّف على أداتك الأولى التي ستراها في كل مثالٍ تاليّ: console.log(). هذا الأمر يطبع ما تضعه بين قوسيه في «الكونسول» (Console)، وهي لوحةٌ مخفيةٌ في أدوات المطوّر بمتصفّحك تفتحها بمفتاح F12 ثمّ تبويب Console. هي نافذتك إلى ما يجري داخل شيفرتك: تطبع بها قيمة متغيّرٍ لتتأكّد منها، أو رسالةً لتعرف أن سطرًا نُفِّذ. وهي أيضًا حيث تظهر رسائل الأخطاء، فاعتد على فتحها من اليوم الأوّل. وتكتب التعليقات في JavaScript بـ// للسطر الواحد، أو بين /* و*/ لعدّة أسطر؛ يتجاهلها المتصفّح وتشرح بها شيفرتك.

المتغيّرات وأنواع البيانات

قبل أن تفعل شيئًا ديناميكيًّا تحتاج إلى تخزين البيانات في «متغيّرات»، وهي أشبه بصناديق بأسماءٍ تضع فيها معلوماتٍ لتستعملها لاحقًا. وفي JavaScript الحديثة طريقتان. ابدأ دائمًا بـconst للقيم التي لن تتغيّر (فهو يمنع أخطاءً عرضية)، واستعمل let فقط حين تحتاج إلى تغيير القيمة لاحقًا:

const blogName = "مدوّنتي التقنية";  // لن يتغيّر
let visitorCount = 10;              // قد يتغيّر
visitorCount = 11;

(قد ترى var في شيفرةٍ قديمة؛ هي الطريقة القديمة ولها سلوكٌ غير متوقّعٍ في المشاريع الكبيرة، فتجنّبها). وأهمّ أنواع البيانات للمبتدئ: String أيّ نصٍّ بين علامتي اقتباس ("مرحبًا")، وNumber أيّ رقمٍ صحيحٍ أو عشريّ (2025)، وBoolean قيمةٌ منطقيةٌ إمّا true أو false، كمفتاح إضاءةٍ يعمل أو لا، وهي حاسمةٌ لاتّخاذ القرارات في الشيفرة.

وكثيرًا ما تحتاج إلى دمج نصٍّ مع قيمة متغيّر، كأن ترحّب باسم المستخدم. الطريقة الحديثة المريحة هي «القوالب النصّية» (Template Literals): تكتب النصّ بين علامتَي شَرطةٍ مائلةٍ خلفية (`) بدل علامتَي الاقتباس، وتدسّ المتغيّر داخله بين ${...}:

const name = "محمد";
console.log(`أهلًا يا ${name}!`);   // أهلًا يا محمد!

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

المنطق: العوامل والشروط والحلقات

«العوامل» رموزٌ تجري عملياتٍ على بياناتك: حسابيةٌ (+ و- و* و/)، ومقارنةٌ نتيجتها true أو false، وأهمّها عامل المساواة الصارم === الذي يتحقّق من تطابق القيمة والنوع معًا. و«الجمل الشرطية» (if...else) هي كيف تجعل الشيفرة تتّخذ قرارًا: إن صحّ شرطٌ فافعل هذا، وإلّا فافعل ذاك:

let userIsLoggedIn = true;
if (userIsLoggedIn === true) {
  console.log("مرحبًا بعودتك!");
} else {
  console.log("يرجى تسجيل الدخول.");
}

ولتنظيم مجموعات البيانات أداتان: «المصفوفة» [] قائمةٌ مرتّبةٌ من العناصر (مثاليةٌ لقائمة أشياء متشابهة، والفهرسة فيها تبدأ من الصفر)، و«الكائن» {} مجموعة أزواج «مفتاح: قيمة» (مثاليٌّ لوصف كيانٍ واحدٍ كمستخدم):

const links = ["Twitter", "LinkedIn", "GitHub"];
console.log(links[0]);  // "Twitter"

const user = { firstName: "محمد", isDeveloper: true };
console.log(user.firstName);  // "محمد"

و«الحلقات التكرارية» تؤدّي الفعل نفسه مرارًا. حلقة for الطريقة الكلاسيكية للمرور على كل عناصر مصفوفة:

const fruits = ["تفاح", "موز", "كرز"];
for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}

وللمصفوفات طريقةٌ حديثةٌ أنظف للمرور على عناصرها هي forEach، تنفّذ دالّةً على كل عنصرٍ دون أن تدير العدّاد بنفسك:

fruits.forEach(function(fruit) {
  console.log(fruit);
});

وهناك أخواتٌ لها ستلقاها كثيرًا، مثل map (تحوّل كل عنصرٍ وتعيد مصفوفةً جديدة) وfilter (تنتقي العناصر التي تحقّق شرطًا). لا تحتجها الآن، لكن اعرف أن هذه «دوال المصفوفات» هي قلب التعامل مع البيانات في جافاسكربت الحديثة.

الوصول للعناصر والاستماع للأحداث

الآن تربط هذا المنطق بعناصر الصفحة الحقيقية، في خطوتين. أوّلًا تجد العنصر عبر جسر JavaScript إلى الـDOM، وهو document، فتستعمل querySelector() تمامًا كما تستهدف في CSS:

const themeButton = document.querySelector('#theme-button');

ثمّ تطلب منه الاستماع لفعلٍ من المستخدم. تُسمّى هذه الأفعال «الأحداث»، وأشهرها النقر 'click'، وتستعمل addEventListener() لتقول للزرّ: «كن متأهّبًا، وحين يُنقَر عليك نفّذ هذه الأوامر».

والنقر ليس الحدث الوحيد. هناك عشراتٌ تستمع إليها بالطريقة نفسها: 'input' حين يكتب المستخدم في حقل (مثاليٌّ للتحقّق الفوريّ)، و'submit' حين يرسل نموذجًا، و'mouseover' حين تمرّ الفأرة فوق عنصر، و'keydown' حين يضغط مفتاحًا. كل تفاعلٍ تراه على الويب هو في جوهره استماعٌ لحدثٍ ثمّ ردُّ فعل.

تنظيم الأوامر: الدوال

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

function greetUser() {
  console.log("أهلًا بك في مدوّنتي!");
}
greetUser();  // استدعاء الدالّة

وتزداد الدالّة قوّةً بأمرين. الأوّل «المُعطيات» (parameters): قيمٌ تمرّرها إليها لتعمل عليها، فتصير الوصفة عامّةً تخدم حالاتٍ كثيرة. والثاني «القيمة المُرجَعة» (return): نتيجةٌ تعيدها الدالّة لتستعملها لاحقًا:

function add(a, b) {   // a و b معطيان
  return a + b;        // تعيد النتيجة
}
const total = add(5, 3);   // total = 8

وستلقى كثيرًا صيغةً أحدث وأقصر للدوال تُسمّى «الدالّة السهمية» (Arrow Function)، جاءت مع ES6، تؤدّي الغرض نفسه بحروفٍ أقلّ، وهي شائعةٌ جدًّا في الشيفرة الحديثة:

const add = (a, b) => a + b;

بدمج هذا كلّه تكتمل القوّة: تجد زرًّا بـquerySelector وتخزّنه في متغيّر، ثمّ تستمع لنقرةٍ بـaddEventListener، وحين تقع تستدعي دالّةً فيها تعليماتك. بهذا تبني أوّل تفاعلٍ حقيقيٍّ في صفحتك، وهو ما تفعله الآن عمليًّا.

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

لمحة عن المكتبات وأطر العمل

ما تعلّمته هنا يُسمّى «JavaScript الخالصة» (Vanilla JS). وفي المشاريع الكبيرة نادرًا ما يبني المطوّرون كل شيءٍ من الصفر، بل يلجؤون إلى أدواتٍ جاهزةٍ تسرّع العمل: «المكتبات» و«أطر العمل». والفرق بينهما في من يتحكّم: المكتبة شيفرةٌ جاهزةٌ أنت تستدعيها حين تحتاج (مثل React)، وإطار العمل هيكلٌ متكاملٌ هو يستدعي شيفرتك ويفرض طريقةً لتنظيم مشروعك (مثل Angular وVue.js). وأشهرها اليوم React (من فيسبوك، تبني الواجهة من «مكوّنات» مستقلّة)، وAngular (من جوجل، حلٌّ شاملٌ للتطبيقات الضخمة)، وVue.js (سهل التعلّم ومرن).

لكنّ نصيحتي: لا تقفز إليها الآن. أتقن أساسيات JavaScript والتلاعب اليدويّ بالـDOM أوّلًا، فهو الأساس الذي تفهم به لاحقًا هذه الأدوات فهمًا صحيحًا بدل أن تستعملها سحرًا لا تفهمه. وهذه الأطر عالمٌ قائمٌ بذاته نفرد له مقالًا خاصًّا في السلسلة: «أطر عمل جافاسكربت».

ولترسم طريقك بعد هذا المقال: رسّخ الأساسيات هنا أوّلًا بمشاريع صغيرةٍ تكتبها بيدك، ثمّ تعمّق في التلاعب بالـDOM وفي الأحداث، ثمّ تعلّم العمل غير المتزامن (جلب البيانات من الخوادم)، وبعد أن تصير هذه كلّها طبيعةً لك، انتقل إلى إطارٍ واحدٍ (يكفيك React بدايةً) وأتقنه قبل أن تجرّب غيره. تشتّتك بين عدّة أطرٍ في البداية يبدّد جهدك؛ العمق في واحدٍ خيرٌ من سطحيةٍ في الجميع.

مشروعٌ عمليّ: زرّ الوضع الليليّ

لنبثّ الحياة في مشروعك: زرٌّ يبدّل الصفحة بين الوضعين النهاريّ والليليّ، وهذا التفاعل أساس كل شيءٍ ديناميكيٍّ على الويب. أوّلًا أضِف الزرّ إلى index.html داخل <nav>، وأعطه معرّفًا فريدًا لتجده بسهولة:

<button id="theme-toggle-button">تفعيل الوضع الليلي</button>

ثانيًا، تذكّر أن JavaScript لا تغيّر الألوان بنفسها، بل تأمر المتصفّح أن «يُلبس» الصفحة زيّ الوضع الليليّ المُعدّ سلفًا. فأضِف هذه القواعد في نهاية style.css، تنشط حين يضاف الصنف dark-mode إلى <body>:

body.dark-mode {
  background-color: #121212;
  color: #f5f5f5;
}
.dark-mode .container {
  background-color: #1e1e1e;
}
.dark-mode header h1 { color: #bb86fc; }

ثالثًا أنشئ ملفّ script.js واربطه قبل </body> بـ<script src="script.js"></script>. ثمّ اكتب فيه الشيفرة التي تربط كل ما تعلّمته:

// 1. إيجاد العناصر وتخزينها
const themeToggleButton = document.querySelector('#theme-toggle-button');
const body = document.querySelector('body');

// 2. تعريف الدالّة التي تقوم بالعمل
function toggleTheme() {
  // إضافة الصنف إن غاب، وإزالته إن وُجد
  body.classList.toggle('dark-mode');

  // تغيير نص الزرّ بحسب الحالة
  if (body.classList.contains('dark-mode')) {
    themeToggleButton.textContent = "تفعيل الوضع النهاري";
  } else {
    themeToggleButton.textContent = "تفعيل الوضع الليلي";
  }
}

// 3. ربط الحدث بالدالّة
themeToggleButton.addEventListener('click', toggleTheme);

احفظ ملفّاتك، وانقر الزرّ: تتحوّل الصفحة كلّها إلى الوضع الداكن، ويتغيّر نصّ الزرّ. لاحظ كيف اجتمعت المفاهيم: متغيّرٌ يخزّن العنصر، ومستمع حدثٍ ينتظر النقرة، ودالّةٌ تنفّذ التبديل، وجملةٌ شرطيةٌ تقرّر نصّ الزرّ. بهذا ربطت «العقل» (المنطق) بـ«الهيكل» (العناصر) بـ«الزيّ» (التصميم)، وهو أساس كل تطبيق ويبٍ حديث.

وإن أردت أن تخطو خطوةً أبعد بنفسك، جرّب تحسينًا حقيقيًّا: اجعل الصفحة «تتذكّر» اختيار المستخدم. فحاليًّا إن أعاد تحميل الصفحة عاد الوضع النهاريّ. تستطيع بـlocalStorage (مخزنٍ صغيرٍ في المتصفّح) أن تحفظ تفضيله وتطبّقه عند كل زيارة. لا تقلق إن لم تعرف كيف الآن؛ هذا بالضبط نوع التحدّي الذي تنمو به: تبحث، وتجرّب، وتقرأ التوثيق، حتى يعمل. هكذا يتعلّم المطوّر فعلًا: لا بالحفظ، بل بحلّ مشكلةٍ حقيقيةٍ بيده.

الصفحة بعد تفعيل الوضع الليلي عبر JavaScript.

بثثت الحياة، فإلى شبكة الأمان

بوصولك إلى هنا أتقنت الأركان الثلاثة لبناء أيّ واجهة ويب: هيكلٌ بـHTML، وكساءٌ بـCSS، وروحٌ تتفاعل مع المستخدم بـJavaScript. لم يعد مشروعك تمثالًا ثابتًا، بل صار كائنًا حيًّا يستجيب للمسة، وتحوّلت من بناء المستندات إلى بناء التطبيقات.

ومع هذه القيمة الجديدة يأتي سؤال: كيف تحمي مشروعك وتتتبّع تطوّره وتجرّب ميزاتٍ جديدةً بأمانٍ دون خوفٍ من إفساد ما بنيته؟ هنا تنتقل من التفكير ككاتب شيفرةٍ إلى التفكير كمهندس برمجيات. في المقال التالي تتعلّم أهمّ أداةٍ في حزام المطوّر لذلك: «نظام التحكّم بالإصدارات Git ومنصّة GitHub».

المصادر

  1. MDN: ما هي JavaScript. لغة برمجةٍ تضيف السلوك والتفاعل إلى الصفحة.
  2. Node.js: عن Node.js. تشغيل JavaScript على الخادم منذ 2009.
  3. Wikipedia: JavaScript. صنع Brendan Eich اللغة في Netscape سنة 1995 وأصل التسمية.
  4. TC39 / ECMA: معيار ECMAScript. المعيار الرسميّ الذي تُبنى عليه JavaScript.
  5. MDN: نموذج كائن المستند (DOM). الشجرة الحيّة التي تتفاعل معها JavaScript.

اترك تعليقاً

الحقول المميّزة بـ مطلوبة