Skip to content

دليل JavaScript المتعمق

مقدمة

لقد تعلمت HTML و CSS، ويمكنك الآن إنشاء صفحات ويب جميلة. لكنك قد تلاحظ: النقر على الأزرار لا يفعل شيئًا، تعبئة النماذج لا تُرسل، صفحة الويب تبدو وكأنها صورة "ثابتة".

هذا هو سبب حاجتنا إلى JavaScript — إنها تجعل صفحة الويب "تنبض بالحياة". النقر على زر يظهر قائمة، كتابة نص تُشغّل بحثًا فوريًا، التمرير في الصفحة يُحمّل المزيد من المحتوى... كل هذه التأثيرات التفاعلية تعتمد على JavaScript.

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

  • قراءة الكود الذي يكتبه الذكاء الاصطناعي وفهم ما يفعله
  • اكتشاف المشاكل في الكود
  • إخبار الذكاء الاصطناعي بكيفية التعديل بوضوح

ماذا ستتعلم في هذا المقال؟

الفصلالمحتوىماذا يمكنك أن تفعل بعد تعلمه
الفصل 1ما هي JavaScriptفهم الدور الذي تلعبه في صفحات الويب
الفصل 2البيانات والمتغيراتمعرفة كيف يخزن البرنامج الأشياء وكيف يستخدمها
الفصل 3الدوال والمنطققراءة منطق الشروط والتكرار وإعادة الاستخدام في الكود
الفصل 4DOM والأحداثمعرفة كيف يتحكم الكود في صفحة الويب وكيف يستجيب لعمليات المستخدم
الفصل 5مهارات عمليةكيفية قراءة كود الذكاء الاصطناعي، وماذا تقول عند مواجهة الأخطاء

كل فصل يبدأ من "القدرة على التعرف على الكود"، لا تحتاج إلى كتابته يدويًا. عندما تصادف كودًا لا تفهمه، عد إلى هنا في أي وقت للرجوع إليه.


1. ما هي JavaScript

🤔 السؤال الأساسي

لماذا تحتاج صفحات الويب إلى JavaScript؟ HTML و CSS يمكنهما بالفعل إعطاء صفحة الويب محتوى وتصميمًا، فلماذا نحتاج إلى تعلم لغة جديدة؟

1.1 من "صفحة ويب ثابتة" إلى "تطبيق ديناميكي"

📄 صفحة ويب بدون JavaScript

  • المحتوى ثابت، لا يمكن التفاعل معه
  • النقر على الأزرار لا يفعل شيئًا
  • تعبئة النماذج لا تُرسل
  • الصفحة لا تُحدّث تلقائيًا

مثل ملصق ورقي، يمكنك فقط النظر إليه

🚀 صفحة ويب مع JavaScript

  • النقر على زر يظهر قائمة
  • كتابة نص تُشغّل بحثًا فوريًا
  • التمرير يُحمّل المحتوى تلقائيًا
  • البيانات تُعرض وتُحدّث في الوقت الفعلي

مثل تطبيق حقيقي

فهم العلاقة بين الثلاثة في جملة واحدة:

التقنيةالتشبيهالدور
HTMLالهيكل العظميتعريف هيكل ومحتوى صفحة الويب
CSSالجلد/المظهرتعريف مظهر وتصميم صفحة الويب
JavaScriptالعضلات والجهاز العصبيجعل صفحة الويب تستجيب وتتفاعل وتفكر

1.2 لماذا يحتاج vibecoding أيضًا إلى فهم JavaScript؟

قصة مطور مبتدئ في JavaScript

بدأ مطور مبتدئ في JavaScript باستخدام الذكاء الاصطناعي لصنع تطبيق "عداد": ينقر على زر، فيزيد الرقم بمقدار 1. الكود الذي أنشأه الذكاء الاصطناعي كان يعمل بشكل طبيعي.

لكنه أراد تغييره إلى "النقر يزيد بمقدار 2"، فقال للذكاء الاصطناعي: "اجعل كل نقرة تزيد بمقدار 2." عدّل الذكاء الاصطناعي الكود، لكن الرقم ظل يزيد بمقدار 1 فقط.

سأل الذكاء الاصطناعي لماذا لم ينجح التعديل، فشرح له الذكاء الاصطناعي، لكنه لم يفهم ما معنى count = count + 1 في الكود، ولم يعرف ما إذا كان هذا هو المكان الذي عدّله الذكاء الاصطناعي أم لا. لم يستطع سوى تكرار "الزيادة بمقدار 2 لا تعمل"، فعدّل الذكاء الاصطناعي عدة نسخ، بعضها جعل القيمة الابتدائية 2، وبعضها أضاف 2 في مكان غير ذي صلة تمامًا.

أخيرًا، قرأ مفهوم "المتغيرات" في الفصل 2، وفهم أن count = count + 1 تعني إضافة 1 إلى قيمة count ثم تخزينها مرة أخرى. ثم قال للذكاء الاصطناعي: "غيّر count + 1 إلى count + 2."

تم التعديل بشكل صحيح من المرة الأولى.

لهذا السبب تحتاج إلى فهم JavaScript — ليس لكتابة الكود يدويًا، ولكن لتتمكن من اكتشاف المشكلة بنظرة واحدة وقول الكلمة المناسبة في الوقت المناسب عندما لا يعدّل الذكاء الاصطناعي الكود بشكل صحيح.

1.3 نظرة أولية: كود حقيقي من الذكاء الاصطناعي

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

السيناريو: صنع وظيفة "النقر على زر لتغيير لون الخلفية"

javascript
// تعريف مجموعة من الألوان
const colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4']
let currentIndex = 0

// العثور على الزر في الصفحة
const button = document.querySelector('#changeBtn')

// إضافة حدث النقر إلى الزر
button.addEventListener('click', () => {
  currentIndex = (currentIndex + 1) % colors.length
  document.body.style.backgroundColor = colors[currentIndex]
})

ماذا يفعل هذا الكود؟

الكودالدورالفصل المقابل
const colors = [...]تعريف مجموعة من بيانات الألوانالفصل 2: المصفوفات
let currentIndex = 0تسجيل اللون المعروض حاليًاالفصل 2: المتغيرات
document.querySelector(...)العثور على الزر في الصفحةالفصل 4: البحث في DOM
button.addEventListener(...)إضافة حدث النقر إلى الزرالفصل 4: مراقبة الأحداث
() => {...}تعريف الكود الذي سيُنفذ بعد النقرالفصل 3: دوال السهم

💡 الفكرة الأساسية

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


2. البيانات: المتغيرات وأنواع البيانات

🤔 السؤال الأساسي

كيف "يتذكر" البرنامج الأشياء؟ المحتوى الذي يدخله المستخدم، البيانات المُستلمة من الخادم، النتائج الوسيطة أثناء الحساب — أين تُخزن هذه المعلومات؟

2.1 المتغيرات: إعطاء اسم للبيانات

المتغير مثل صندوق عليه ملصق — يمكنك وضع البيانات فيه، واسترجاعها لاحقًا من خلال الملصق.

javascript
const name = "张三"   // الاسم لن يتغير، استخدم const
let age = 25          // العمر قد يتغير، استخدم let

لماذا نفرق بين const و let؟

تخيل: رقم هويتك (const) لن يتغير طوال حياتك، لكن عمرك (let) يتغير كل عام. تتيح لك JavaScript استخدام كلمات مفتاحية مختلفة للتعبير عن نية "التغيير وعدم التغيير".

الكلمة المفتاحيةهل يمكن التعديلحالة الاستخداممثال
const❌ لا يمكنبيانات لن تتغير قيمتهارقم الهوية، عناصر التكوين، قائمة الألوان
let✅ يمكنبيانات ستتغير قيمتهاالعداد، الخيار المحدد حاليًا، إدخال المستخدم
🔍 مثال ملموس
javascript
// استخدام const: هذه القيم لن تتغير
const PI = 3.14159
const MAX_USERS = 100
const APP_NAME = "TodoList"

// استخدام let: هذه القيم ستتغير
let count = 0
count = 1  // ✅ يمكن التعديل

count = count + 1  // ✅ يمكن الحساب بناءً على القيمة الأصلية

// ماذا لو استخدمنا const؟
const fixedCount = 0
fixedCount = 1  // ❌ خطأ! const لا يمكن إعادة تعيين قيمتها

👇 جرب بنفسك: عدّل الكود التالي لترى الفرق بين const و let

📦 Variables Are Named Boxes
const
name
Alice
🔒
let
age
25
🔓
const
isStudent
true
🔒
const name = "Alice"let age = 25

2.2 أنواع البيانات: أنواع "الأشياء" في JavaScript

تقسم JavaScript البيانات إلى عدة أنواع، أكثرها استخدامًا ثلاثة:

النوعالوصفمثالسيناريو واقعي
string (نص)محتوى نصي"hello", '你好'اسم المستخدم، وصف المنتج، رسائل التنبيه
number (رقم)قيمة عددية42, 3.14السعر، الكمية، التقييم
boolean (قيمة منطقية)نعم/لاtrue, falseهل سجل الدخول، هل اكتمل، هل هو مرئي

هناك قيمتان خاصتان يجب معرفتهما:

  • undefined → تم تعريف المتغير لكن لم تُعطَ له قيمة بعد
  • null → تم تعيينه فارغًا عن قصد (يعني "لا توجد قيمة هنا")
🔍 القوالب النصية: طريقة أسهل لدمج النصوص

في كود الذكاء الاصطناعي، غالبًا ما ترى نصوصًا محاطة بعلامات backtick (`) وبداخلها ${...}:

javascript
const name = "张三"
const age = 25

// الطريقة التقليدية (مزعجة)
const message = "我叫" + name + ",今年" + age + "岁"

// القالب النصي (بسيط)
const message = `我叫${name},今年${age}岁`
// النتيجة: "我叫张三,今年25岁"

نقطة التعرف: عندما ترى backtick و ${}، فاعلم أنه يتم إدراج متغيرات في النص.

2.3 الكائنات والمصفوفات: تنظيم البيانات

الكائن = مجموعة من الخصائص المسماة (مثل نموذج معلومات شخصية)

javascript
const user = {
  name: "张三",
  age: 25,
  isVIP: true
}

// استخدام النقطة للوصول إلى الخصائص
console.log(user.name)    // "张三"
console.log(user.age)     // 25

المصفوفة = مجموعة من البيانات المرتبة (مثل قائمة)

javascript
const colors = ['أحمر', 'أخضر', 'أزرق']

// الوصول بالفهرس (يبدأ من 0)
console.log(colors[0])  // "أحمر"
console.log(colors[1])  // "أخضر"

الهياكل المتداخلة: كائنات داخل مصفوفات، مصفوفات داخل كائنات

هذا هو هيكل البيانات الأكثر شيوعًا في كود الذكاء الاصطناعي:

javascript
const todos = [
  { id: 1, text: "تعلم JavaScript", done: false },
  { id: 2, text: "العمل على مشروع", done: true },
  { id: 3, text: "كتابة وثائق", done: false }
]

// الوصول: أولاً خذ العنصر 0 من المصفوفة، ثم خاصية text منه
console.log(todos[0].text)  // "تعلم JavaScript"

💡 مهارة التعرف

  • رؤية {} → هذا كائن، بداخله مجموعة من اسم: قيمة
  • رؤية [] → هذه مصفوفة، بداخلها مجموعة من القيم المرتبة
  • رؤية data[0].name → أولاً خذ العنصر 0 من المصفوفة، ثم خاصية name منه

2.4 القيمة vs المرجع: فخ شائع

هذه من أكثر المشاكل التي يواجهها المبتدئون!

تعيين الأنواع الأساسية (string، number، boolean) = نسخ بيانات جديدة بالكامل:

javascript
let a = 10
let b = a      // b يحصل على نسخة من a
b = 20
console.log(a) // 10 (a لم يتأثر)

تعيين الكائنات والمصفوفات = نسخ "العنوان" (يشيران إلى نفس الشيء):

javascript
let user1 = { name: "张三" }
let user2 = user1      // user2 يشير إلى نفس الكائن
user2.name = "李四"     // تعديل user2 سيؤثر على user1
console.log(user1.name) // "李四" (user1 تغير أيضًا!)

لماذا ننشئ نسخًا؟

في React/Vue، تعديل البيانات مباشرة يؤدي إلى عدم تحديث الواجهة. لذلك غالبًا ما ترى [...array] أو {...obj} في كود الذكاء الاصطناعي — إنه ينشئ نسخة لتجنب التأثير المتبادل.

javascript
// استخدام معامل النشر لإنشاء نسخة
const arr1 = [1, 2, 3]
const arr2 = [...arr1]     // إنشاء مصفوفة جديدة
arr2.push(4)
console.log(arr1)          // [1, 2, 3] (لم يتأثر)
console.log(arr2)          // [1, 2, 3, 4]

👇 جرب بنفسك: لاحظ كيف تتغير البيانات الأصلية عند تعديل النسخة

2.5 التفكيك والنشر: اختصارات JavaScript الحديثة

هاتان الصيغتان منتشرتان في كل مكان في كود الذكاء الاصطناعي، إن لم تتعرف عليهما فلن تفهم الكود.

التفكيك (Destructuring): استخراج البيانات بسرعة من الكائنات أو المصفوفات

javascript
const user = { name: "张三", age: 25, city: "北京" }

// الطريقة التقليدية (مزعجة)
const name = user.name
const age = user.age

// طريقة التفكيك (بسيطة)
const { name, age } = user
// نفس النتيجة، لكن في سطر واحد

معامل النشر (Spread): نسخ وتوسيع البيانات

javascript
// نسخ مصفوفة وإضافة عناصر جديدة
const arr1 = [1, 2, 3]
const arr2 = [...arr1, 4, 5]  // [1, 2, 3, 4, 5]

// نسخ كائن وإضافة خصائص جديدة
const user1 = { name: "张三", age: 25 }
const user2 = { ...user1, city: "北京" }
// { name: "张三", age: 25, city: "北京" }

💡 مهارة التعرف

  • رؤية const { name, age } = person → استخراج name و age من كائن person
  • رؤية ...array أو ...obj → نشر (توسيع) المصفوفة أو الكائن
  • لا تحتاج إلى كتابتها يدويًا، لكن يجب أن تكون قادرًا على قراءتها

3. المنطق: الدوال والتحكم في التدفق

🤔 السؤال الأساسي

كيف "يتخذ الكود قرارات" و"يكرر الأشياء"؟ البرنامج يحتاج إلى تنفيذ عمليات مختلفة حسب الشروط، ويحتاج أيضًا إلى تكرار مهام معينة — كيف يُعبَّر عن هذا المنطق؟

3.1 الشروط: إذا... فـ... وإلا...

if/else: أبسط أشكال الحكم الشرطي

javascript
const age = 18

if (age >= 18) {
  console.log("بالغ")
} else {
  console.log("قاصر")
}

المعامل الثلاثي: اختصار لـ if/else

javascript
// الطريقة الكاملة (4 أسطر)
let message
if (age >= 18) {
  message = "بالغ"
} else {
  message = "قاصر"
}

// المعامل الثلاثي (سطر واحد)
const message = age >= 18 ? "بالغ" : "قاصر"
// الصيغة: الشرط ? القيمة عندما يكون الشرط صحيحًا : القيمة عندما يكون الشرط خاطئًا

طريقة الاختصار &&: شائعة في كود React

javascript
// فقط عندما يكون isLoggedIn قيمته true، يتم عرض لوحة المستخدم
isLoggedIn && <UserPanel />

// تكافئ
if (isLoggedIn) {
  return <UserPanel />
}

💡 مهارة التعرف

  • رؤية ? : → هذا هو المعامل الثلاثي، اختصار لـ if/else
  • رؤية && → ما قبله true، نفذ ما بعده

3.2 الدوال: تغليف العمليات

الدالة = وصفة طبق

  • تعريف الدالة = كتابة الوصفة
  • استدعاء الدالة = الطهي حسب الوصفة
  • المعاملات (parameters) = المكونات
  • القيمة المُرجعة (return value) = الطبق النهائي
javascript
// تعريف الدالة (كتابة الوصفة)
function greet(name) {
  return "Hello " + name
}

// استدعاء الدالة (الطهي حسب الوصفة)
console.log(greet("张三"))  // "Hello 张三"
console.log(greet("李四"))  // "Hello 李四"

ثلاث طرق للكتابة، تعرف عليها بنظرة واحدة:

javascript
// 1. تعريف function (الطريقة التقليدية)
function greet(name) {
  return "Hello " + name
}

// 2. دالة السهم (الأكثر استخدامًا في كود الذكاء الاصطناعي)
const greet = (name) => {
  return "Hello " + name
}

// 3. اختصار دالة السهم (عندما يكون هناك سطر واحد فقط)
const greet = (name) => "Hello " + name

👇 جرب بنفسك: أدخل أسماء مختلفة لترى كيف تعمل الدالة

💡 مهارة التعرف

  • رؤية function أو => → هذه دالة
  • رؤية fn() → يتم استدعاء هذه الدالة
  • رؤية () => {} → دالة السهم، الطريقة السائدة في JavaScript الحديثة

3.3 دوال المصفوفات: أدوات قوية للتعامل مع القوائم

في React/Vue، تقريبًا كل عرض قائمة يستخدم هذه الدوال.

javascript
const todos = [
  { id: 1, text: "تعلم", done: false },
  { id: 2, text: "عمل", done: true }
]

// .map(): تحويل كل عنصر في المصفوفة إلى شيء آخر
const texts = todos.map(todo => todo.text)
// ["تعلم", "عمل"]

// .filter(): تصفية العناصر المطابقة للشرط
const unfinished = todos.filter(todo => !todo.done)
// [{ id: 1, text: "تعلم", done: false }]

// .find(): إيجاد أول عنصر مطابق للشرط
const found = todos.find(todo => todo.id === 1)
// { id: 1, text: "تعلم", done: false }

💡 مهارة التعرف

  • رؤية .map() → تحويل المصفوفة، وإرجاع مصفوفة جديدة
  • رؤية .filter() → تصفية المصفوفة
  • رؤية items.map(item => <li>{item.name}</li>) → تحويل كل عنصر بيانات إلى وسم قائمة

3.4 النطاق (Scope): "المدى المرئي" للمتغيرات

تشبيه "الغرفة":

  • المتغيرات داخل الدالة مثل الأشياء في الغرفة، لا يمكن رؤيتها من الخارج
  • لكن من في الغرفة يمكنه رؤية الأشياء في الممر (النطاق الخارجي)
javascript
const global = "متغير عام"  // أشياء في الممر

function room() {
  const local = "أشياء في الغرفة"  // أشياء في الغرفة
  console.log(global)  // ✅ يمكن رؤية الممر
}

console.log(local)  // ❌ خطأ! لا يمكن رؤية الأشياء في الغرفة من الخارج

الحدس الأساسي: مكان كتابة الكود يحدد ما يمكنه رؤيته من متغيرات.

👇 جرب بنفسك: انقر على نطاقات مختلفة لترى أي المتغيرات يمكن الوصول إليها

🔍 Scope: where variables are visible

Global scope
appName= "Todo"
Function scope: greet()
appName= "Todo"← global
message= "Hello"
Block scope: if
appName= "Todo"← global
message= "Hello"← function
greeting= message+appName
💡 Variables visible here
In global scope, only the global variable appName is available.

Matching code

const appName = "Todo"  // global scope

function greet() {
  const message = "Hello"  // function scope

  if (true) {
    const greeting = message + appName  // block scope
    console.log(greeting)
  }

  console.log(greeting)  // ❌ Error. Outer code cannot see inner variables.
}

3.5 الإغلاق (Closure): الدالة "تتذكر" البيئة التي وُلدت فيها

لا تعتبرها مفهومًا مستقلًا، بل افهمها من خلال سيناريو ملموس:

javascript
function setupCounter() {
  let count = 0  // هذا المتغير داخل الدالة

  return {
    add: () => { count++; return count },
    getCount: () => count
  }
}

const counter = setupCounter()
console.log(counter.add())      // 1
console.log(counter.add())      // 2
console.log(counter.getCount()) // 2

الحدس الأساسي: عندما تُنشأ الدالة، فإنها "تتذكر" المتغيرات المحيطة بها، حتى بعد انتهاء تنفيذ الدالة الخارجية.

👇 جرب بنفسك: لاحظ كيف يجعل الإغلاق الدالة "تتذكر" الحالة

3.6 this: من استدعى الدالة

لن نشرح قواعد الربط المعقدة، فقط السيناريوهات الأكثر شيوعًا:

السيناريو 1: داخل دوال الكائن، this يشير إلى هذا الكائن

javascript
const user = {
  name: "张三",
  sayHi() {
    console.log("مرحبًا، أنا " + this.name)  // this يشير إلى user
  }
}
user.sayHi()  // "مرحبًا، أنا 张三"

السيناريو 2: في مراقبة الأحداث، this يشير إلى العنصر الذي أطلق الحدث

javascript
button.addEventListener('click', function() {
  console.log(this)  // this يشير إلى عنصر button
})

// لكن دوال السهم لا تغير this
button.addEventListener('click', () => {
  console.log(this)  // this يشير إلى this الخارجي
})

💡 ماذا تفعل عند مواجهة مشكلة؟

إذا ظهر خطأ متعلق بـ this في كود الذكاء الاصطناعي (مثل Cannot read property of undefined)، أخبر الذكاء الاصطناعي: "this في هذه الدالة لا يشير إلى المكان الصحيح، غيّرها إلى دالة سهم أو استخدم bind"


4. التفاعل: DOM والأحداث والعمليات غير المتزامنة

🤔 السؤال الأساسي

كيف يتفاعل JavaScript مع صفحة الويب؟ كيف يعثر على العناصر في الصفحة؟ كيف يستجيب لنقرات المستخدم وإدخالاته؟ كيف يحصل على البيانات من الخادم؟

4.1 DOM: صفحة الويب كما يراها JavaScript

صفحة الويب في عيون JavaScript هي "شجرة"، كل وسم HTML هو "عقدة" في الشجرة.

html
<html>
  <body>
    <h1>عنوان</h1>
    <p>فقرة</p>
    <ul>
      <li>عنصر 1</li>
      <li>عنصر 2</li>
    </ul>
  </body>
</html>

تحكم JS في صفحة الويب = العثور على العقدة + تعديل العقدة + إنشاء/حذف العقدة

👇 جرب بنفسك: انقر على العقد لترى كيف تنتظم شجرة DOM

DOM Tree: the Webpage JavaScript Sees

My page

Welcome

  • Item 1
  • Item 2
<html>
<body>
<h1>My page
<p>Welcome
<ul>
<li>Item 1
<li>Item 2

Matching code

Click a button above to see the matching code

4.2 البحث عن العناصر وتعديلها

البحث عن العناصر:

javascript
// البحث باستخدام محددات CSS (الأكثر استخدامًا)
const title = document.querySelector('h1')      // ابحث عن أول h1
const button = document.querySelector('#btn')   // ابحث عن العنصر ذو id="btn"
const items = document.querySelectorAll('.item') // ابحث عن جميع العناصر ذات class="item"

تعديل العناصر:

javascript
// تغيير النص
title.textContent = "عنوان جديد"

// تغيير التنسيق
element.style.color = "red"
element.style.fontSize = "20px"

// تغيير فئات CSS
element.classList.add('active')      // إضافة فئة
element.classList.remove('hidden')   // إزالة فئة
element.classList.toggle('open')     // تبديل الفئة (تضاف إذا لم تكن موجودة، وتُزال إذا كانت موجودة)

💡 مهارة التعرف

  • رؤية document.querySelector → البحث عن عنصر في صفحة الويب
  • رؤية .textContent → تغيير النص
  • رؤية .style.xxx → تغيير التنسيق
  • رؤية .classList.add/remove/toggle → تغيير فئات CSS

4.3 الأحداث: عندما يقوم المستخدم بعملية معينة...

addEventListener: إضافة مراقبة الأحداث إلى عنصر

javascript
button.addEventListener('click', () => {
  console.log("تم النقر على الزر")
})

الأحداث الشائعة:

الحدثوقت الإطلاقسيناريو واقعي
clickالنقرالنقر على الأزرار، الانتقال بالروابط
inputتغير محتوى حقل الإدخالالبحث الفوري، التحقق من النماذج
submitإرسال النموذجتسجيل الدخول، التسجيل، إرسال البيانات
scrollتمرير الصفحةالتحميل الكسول، العودة إلى الأعلى

كائن الحدث: الحصول على مزيد من المعلومات

javascript
input.addEventListener('input', (e) => {
  console.log(e.target.value)  // الحصول على قيمة حقل الإدخال
  e.preventDefault()            // منع السلوك الافتراضي (مثل تحديث الصفحة بعد إرسال النموذج)
})

💡 تطبيق عملي

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

4.4 العمليات غير المتزامنة: لماذا بعض العمليات لا تكتمل فورًا

تشبيه المطعم:

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

السيناريو الأكثر شيوعًا: جلب البيانات من الخادم

javascript
// الطريقة المتزامنة (ستجمد الصفحة، لا تستخدمها)
const data = fetch('/api/data')  // ❌ الكتابة بهذه الطريقة ستجمد الصفحة

// الطريقة غير المتزامنة (صحيحة)
async function loadData() {
  try {
    const response = await fetch('/api/data')
    const data = await response.json()
    console.log(data)
  } catch (error) {
    console.error('حدث خطأ:', error)
  }
}

صيغة async/await:

  • async → تعليم أن هذه الدالة تحتوي على عمليات غير متزامنة
  • await → انتظار اكتمال هذه العملية (لكن دون تجميد الصفحة)
  • try/catch → معالجة الأخطاء المحتملة

👇 جرب بنفسك: لاحظ ترتيب تنفيذ العمليات غير المتزامنة

💡 مهارة التعرف

  • رؤية async/await → في انتظار عملية تستغرق وقتًا
  • رؤية fetch() → جلب البيانات من الخادم
  • رؤية try/catch → معالجة الأخطاء المحتملة

4.5 حلقة الأحداث: كيف يعمل JavaScript فعليًا

بدون مصطلحات "المهام الدقيقة/المهام الكبيرة"، استخدم نموذجًا بسيطًا للفهم:

JS هي "محطة عمل فردية"، تفعل شيئًا واحدًا فقط في كل مرة، لكن لديها "لوحة مهام ورقية" (طابور المهام).

عند مواجهة عملية تحتاج إلى انتظار (طلب شبكة، مؤقت)، لا تنتظر JS بغباء، بل تضع "ماذا تفعل بعد انتهاء الانتظار" على اللوحة، وتستمر في التنفيذ. وعندما تنتهي من العمل الحالي، تذهب لتفقد اللوحة.

javascript
console.log("1")

setTimeout(() => console.log("2"), 0)  // حتى لو كانت 0 ثانية، سيتم التأجيل

console.log("3")

// الناتج: 1, 3, 2 (وليس 1, 2, 3!)

لماذا؟

  1. تنفيذ console.log("1") → إخراج 1
  2. مواجهة setTimeout → وضع دالة الرد على اللوحة، والمتابعة
  3. تنفيذ console.log("3") → إخراج 3
  4. انتهى تنفيذ الكود الحالي، الذهاب لتفقد اللوحة
  5. تنفيذ دالة رد setTimeout → إخراج 2

👇 جرب بنفسك: لاحظ ترتيب تنفيذ الكود

Event Loop: How JavaScript Executes Code

Code queue

1
console.log("1")
Executing
2
setTimeout(() => console.log("2"), 0)
3
console.log("3")
4
fetch("/api").then(() => console.log("4"))
5
console.log("5")

Worker (single thread)

👨‍💻
Running
Run console.log("1")

Task queue

No pending tasks

Output log

Waiting for output...

Execution order: not started

Written order: 1, 2, 3, 4, 5

Code is written top to bottom, but it does not always run top to bottom because async work is delayed until the current code finishes.

💡 ماذا تفعل عند مواجهة مشكلة؟

إذا كان كود الذكاء الاصطناعي يعرض الصفحة قبل وصول البيانات، أخبر الذكاء الاصطناعي: "البيانات لم تُحمّل بعد وبدأ العرض، أحتاج إلى إضافة حالة loading، وانتظر حتى تصل البيانات ثم اعرضها"

4.6 الوحدات: import و export

أول سطر في كود React/Vue الذي ينشئه الذكاء الاصطناعي يكون دائمًا تقريبًا import.

import = استيراد وظائف من ملف آخر

javascript
// استيراد دالة من ملف أدوات
import { formatDate } from './utils'

// استيراد من حزمة خارجية
import React from 'react'
import { useState } from 'react'

export = تصدير الوظائف ليستخدمها الآخرون

javascript
// utils.js
export function formatDate(date) {
  // ...
}

// أو تصدير افتراضي
export default function formatDate(date) {
  // ...
}

حزمة npm = أدوات كتبها آخرون، يمكنك استخدامها بعد التثبيت

javascript
// تثبيت الحزمة: npm install lodash
// استخدام الحزمة
import _ from 'lodash'

💡 مهارة التعرف

  • رؤية import → استيراد وظائف من ملف آخر
  • رؤية export → تصدير الوظائف ليستخدمها الآخرون
  • رؤية from 'react' → استيراد من حزمة React
  • رؤية from './utils' → استيراد من ملف محلي

5. التطبيق العملي: قراءة الكود، فهم الأخطاء، والوصف الدقيق

🤔 السؤال الأساسي

تعلمت كل هذه الصيغ، كيف تستخدمها فعليًا عندما تحصل على كود من الذكاء الاصطناعي؟ كيف تقرأ الكود بسرعة؟ ماذا تفعل عند مواجهة خطأ؟ كيف تجعل الذكاء الاصطناعي يعدل الكود بدقة؟

5.1 كيف تقرأ كود الذكاء الاصطناعي

طريقة الخطوات الأربع:

الخطوةماذا تنظرمثال
الخطوة الأولى: انظر إلى الهيكل العامكم عدد الدوال؟ ماذا تفعل كل منها؟loadData() تحميل البيانات، renderList() عرض القائمة
الخطوة الثانية: ابحث عن نقطة الدخولمن أين يبدأ تنفيذ البرنامج؟addEventListener('click', ...) يبدأ عند النقر
الخطوة الثالثة: تتبع تدفق البياناتمن أين تأتي البيانات؟ إلى أين تذهب؟من API → تحليل → عرض على الصفحة
الخطوة الرابعة: انظر إلى المنطق التفصيليكيف تعالج الدوال المحددة؟حلقات، شروط، حسابات

استخدام مثال الكود من الفصل 1 لعمل "عرض قراءة" كامل:

javascript
// الخطوة الأولى: الهيكل العام
// - مصفوفة ألوان
// - متغير لتسجيل الفهرس الحالي
// - حدث نقرة على زر

// الخطوة الثانية: نقطة الدخول
// button.addEventListener('click', ...) → ينفذ عند النقر على الزر

// الخطوة الثالثة: تدفق البيانات
// colors (مصفوفة الألوان) → currentIndex (الفهرس الحالي) → backgroundColor (لون الخلفية)

// الخطوة الرابعة: المنطق التفصيلي
// currentIndex = (currentIndex + 1) % colors.length
// معنى هذه الصيغة: زيادة 1 في كل مرة، لكن لا تتجاوز طول المصفوفة (دوري)

5.2 دليل سريع للأخطاء الشائعة

الخطأشرح مبسطماذا تقول للذكاء الاصطناعي
TypeError: Cannot read properties of undefinedتحاول أخذ قيمة من شيء غير موجود"السطر X به خطأ، المتغير الفلاني قيمته undefined، تحقق من منطق تعيين قيمته"
ReferenceError: xxx is not definedاستخدمت اسم متغير لم يتم تعريفه"المتغير xxx لم يتم تعريفه، هل هناك خطأ إملائي أو نسيت استيراده"
TypeError: xxx is not a functionاستدعيت شيئًا ليس دالة وكأنه دالة"xxx ليس دالة، تحقق من نوعه ومصدره"
SyntaxError: Unexpected tokenخطأ في الصيغة (أقواس غير متطابقة، فاصلة ناقصة، إلخ)"السطر X به خطأ في الصيغة، تحقق من الأقواس وعلامات الترقيم"
CORS errorالمتصفح منع طلبًا عبر النطاقات"واجهت خطأ CORS، أحتاج إلى تكوين مشاركة الموارد عبر النطاقات"
404 Not Foundالمورد المطلوب غير موجود"API يعيد 404، تحقق من صحة عنوان الواجهة"

5.3 كيف تصف المشكلة بدقة

الفرق بين المطور المبتدئ والمتمرس غالبًا ما يظهر في دقة وصف المشكلة.

❌ وصف سيء✅ وصف جيد
"الكود فيه خطأ""عند النقر على زر الحذف، يحذف العنصر الأخير بدلًا من العنصر الحالي"
"التنسيق غير صحيح""العنوان يجب أن يكون في المنتصف، لكنه حاليًا بمحاذاة اليسار"
"البيانات لا تظهر""طلب fetch أعاد البيانات (يمكن رؤيتها في وحدة التحكم)، لكن الصفحة لم تُعِد العرض"
"أضف وظيفة""أضف مربع بحث في صفحة قائمة المستخدمين، يُصفي القائمة فوريًا أثناء الكتابة، مع مطابقة تقريبية حسب حقل name"
"النقر لا يفعل شيئًا""عند النقر على الزر، تظهر في وحدة التحكم رسالة خطأ 'Cannot read property of undefined'، الخطأ في السطر X"

تمرين عملي:

javascript
// كود به خطأ
function deleteTodo(index) {
  todos.splice(index, 1)  // دائمًا يحذف العنصر الأخير
}

// الظاهرة الخاطئة: أيًا كان زر الحذف الذي تنقر عليه، يُحذف العنصر الأخير دائمًا

❌ وصف سيء: "وظيفة الحذف فيها خطأ"

✅ وصف جيد: "عند النقر على زر الحذف، لا يحذف العنصر الحالي بل يحذف العنصر الأخير. الكود يستخدم splice(index, 1)، لكن index قد لا يكون صحيحًا. يحتاج إلى التعديل ليستخدم id الفريد لكل عنصر للحذف المطابق."

5.4 الكود الذي يجب أن تكون قادرًا على التعرف عليه الآن

  • رؤية const/let → معرفة ما إذا كان يمكن إعادة تعيين المتغير
  • رؤية {} → كائن / رؤية [] → مصفوفة
  • رؤية {...obj} أو [...arr] → إنشاء نسخة
  • رؤية function أو => → تعريف عملية قابلة للتكرار
  • رؤية if/else أو ? : → الكود يقوم بحكم شرطي
  • رؤية .map() / .filter() → تحويل أو تصفية مصفوفة
  • رؤية document.querySelector → البحث عن عنصر في صفحة الويب
  • رؤية addEventListener → مراقبة عمليات المستخدم
  • رؤية async/await → انتظار عملية تستغرق وقتًا
  • رؤية import/export → استيراد أو تصدير وحدات
  • مواجهة خطأ → القدرة على فهم المعنى العام ووصفه بدقة للذكاء الاصطناعي

إذا قرأت بعناية أقسام "التعمق" في كل فصل، فأنت أيضًا تتقن هذه المفاهيم الأساسية:

  • القيمة vs المرجع: الأنواع الأساسية تنسخ القيمة، والكائنات/المصفوفات تنسخ العنوان
  • النطاق والإغلاق: الدالة يمكنها "تذكر" المتغيرات المحيطة بها عند إنشائها
  • جوهر this: يعتمد على من استدعى الدالة، وليس على مكان كتابتها
  • حلقة الأحداث: JS أحادية الخيط، وتعتمد على طابور المهام لتحقيق "عدم الحظر"

هذه المفاهيم ستساعدك في تحديد المشاكل بشكل أسرع.

💡 عند مواجهة مشكلة، قل هذا للذكاء الاصطناعي

  • "السطر X به خطأ XXX، ساعدني في معرفة ما المشكلة"
  • "منطق هذه الدالة هو XXX، لكن النتيجة غير صحيحة، يجب أن تكون XXX"
  • "أريد تعديل وظيفة XXX، المتطلبات المحددة هي XXX"