My page
Welcome
- Item 1
- Item 2
مقدمة
لقد تعلمت HTML و CSS، ويمكنك الآن إنشاء صفحات ويب جميلة. لكنك قد تلاحظ: النقر على الأزرار لا يفعل شيئًا، تعبئة النماذج لا تُرسل، صفحة الويب تبدو وكأنها صورة "ثابتة".
هذا هو سبب حاجتنا إلى JavaScript — إنها تجعل صفحة الويب "تنبض بالحياة". النقر على زر يظهر قائمة، كتابة نص تُشغّل بحثًا فوريًا، التمرير في الصفحة يُحمّل المزيد من المحتوى... كل هذه التأثيرات التفاعلية تعتمد على JavaScript.
في vibecoding، سيقوم الذكاء الاصطناعي بكتابة معظم الكود نيابةً عنك. لكنك على الأقل تحتاج أن تكون قادرًا على قراءة الكود وفهم ما يفعله، وإلا فلن تتمكن من اكتشاف أخطاء الذكاء الاصطناعي. بعد قراءة هذا الدليل، ستتمكن من:
ماذا ستتعلم في هذا المقال؟
| الفصل | المحتوى | ماذا يمكنك أن تفعل بعد تعلمه |
|---|---|---|
| الفصل 1 | ما هي JavaScript | فهم الدور الذي تلعبه في صفحات الويب |
| الفصل 2 | البيانات والمتغيرات | معرفة كيف يخزن البرنامج الأشياء وكيف يستخدمها |
| الفصل 3 | الدوال والمنطق | قراءة منطق الشروط والتكرار وإعادة الاستخدام في الكود |
| الفصل 4 | DOM والأحداث | معرفة كيف يتحكم الكود في صفحة الويب وكيف يستجيب لعمليات المستخدم |
| الفصل 5 | مهارات عملية | كيفية قراءة كود الذكاء الاصطناعي، وماذا تقول عند مواجهة الأخطاء |
كل فصل يبدأ من "القدرة على التعرف على الكود"، لا تحتاج إلى كتابته يدويًا. عندما تصادف كودًا لا تفهمه، عد إلى هنا في أي وقت للرجوع إليه.
🤔 السؤال الأساسي
لماذا تحتاج صفحات الويب إلى JavaScript؟ HTML و CSS يمكنهما بالفعل إعطاء صفحة الويب محتوى وتصميمًا، فلماذا نحتاج إلى تعلم لغة جديدة؟
📄 صفحة ويب بدون JavaScript
مثل ملصق ورقي، يمكنك فقط النظر إليه
🚀 صفحة ويب مع JavaScript
مثل تطبيق حقيقي
فهم العلاقة بين الثلاثة في جملة واحدة:
| التقنية | التشبيه | الدور |
|---|---|---|
| HTML | الهيكل العظمي | تعريف هيكل ومحتوى صفحة الويب |
| CSS | الجلد/المظهر | تعريف مظهر وتصميم صفحة الويب |
| JavaScript | العضلات والجهاز العصبي | جعل صفحة الويب تستجيب وتتفاعل وتفكر |
قصة مطور مبتدئ في JavaScript
بدأ مطور مبتدئ في JavaScript باستخدام الذكاء الاصطناعي لصنع تطبيق "عداد": ينقر على زر، فيزيد الرقم بمقدار 1. الكود الذي أنشأه الذكاء الاصطناعي كان يعمل بشكل طبيعي.
لكنه أراد تغييره إلى "النقر يزيد بمقدار 2"، فقال للذكاء الاصطناعي: "اجعل كل نقرة تزيد بمقدار 2." عدّل الذكاء الاصطناعي الكود، لكن الرقم ظل يزيد بمقدار 1 فقط.
سأل الذكاء الاصطناعي لماذا لم ينجح التعديل، فشرح له الذكاء الاصطناعي، لكنه لم يفهم ما معنى count = count + 1 في الكود، ولم يعرف ما إذا كان هذا هو المكان الذي عدّله الذكاء الاصطناعي أم لا. لم يستطع سوى تكرار "الزيادة بمقدار 2 لا تعمل"، فعدّل الذكاء الاصطناعي عدة نسخ، بعضها جعل القيمة الابتدائية 2، وبعضها أضاف 2 في مكان غير ذي صلة تمامًا.
أخيرًا، قرأ مفهوم "المتغيرات" في الفصل 2، وفهم أن count = count + 1 تعني إضافة 1 إلى قيمة count ثم تخزينها مرة أخرى. ثم قال للذكاء الاصطناعي: "غيّر count + 1 إلى count + 2."
تم التعديل بشكل صحيح من المرة الأولى.
لهذا السبب تحتاج إلى فهم 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 هو سلسلة من التعليمات، تخبر المتصفح "ماذا يجب أن يحدث عندما يفعل المستخدم شيئًا معينًا."
🤔 السؤال الأساسي
كيف "يتذكر" البرنامج الأشياء؟ المحتوى الذي يدخله المستخدم، البيانات المُستلمة من الخادم، النتائج الوسيطة أثناء الحساب — أين تُخزن هذه المعلومات؟
المتغير مثل صندوق عليه ملصق — يمكنك وضع البيانات فيه، واسترجاعها لاحقًا من خلال الملصق.
const name = "张三" // الاسم لن يتغير، استخدم const
let age = 25 // العمر قد يتغير، استخدم letلماذا نفرق بين const و let؟
تخيل: رقم هويتك (const) لن يتغير طوال حياتك، لكن عمرك (let) يتغير كل عام. تتيح لك JavaScript استخدام كلمات مفتاحية مختلفة للتعبير عن نية "التغيير وعدم التغيير".
| الكلمة المفتاحية | هل يمكن التعديل | حالة الاستخدام | مثال |
|---|---|---|---|
const | ❌ لا يمكن | بيانات لن تتغير قيمتها | رقم الهوية، عناصر التكوين، قائمة الألوان |
let | ✅ يمكن | بيانات ستتغير قيمتها | العداد، الخيار المحدد حاليًا، إدخال المستخدم |
// استخدام 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
const name = "Alice"let age = 25تقسم JavaScript البيانات إلى عدة أنواع، أكثرها استخدامًا ثلاثة:
| النوع | الوصف | مثال | سيناريو واقعي |
|---|---|---|---|
string (نص) | محتوى نصي | "hello", '你好' | اسم المستخدم، وصف المنتج، رسائل التنبيه |
number (رقم) | قيمة عددية | 42, 3.14 | السعر، الكمية، التقييم |
boolean (قيمة منطقية) | نعم/لا | true, false | هل سجل الدخول، هل اكتمل، هل هو مرئي |
هناك قيمتان خاصتان يجب معرفتهما:
undefined → تم تعريف المتغير لكن لم تُعطَ له قيمة بعدnull → تم تعيينه فارغًا عن قصد (يعني "لا توجد قيمة هنا")في كود الذكاء الاصطناعي، غالبًا ما ترى نصوصًا محاطة بعلامات backtick (`) وبداخلها ${...}:
const name = "张三"
const age = 25
// الطريقة التقليدية (مزعجة)
const message = "我叫" + name + ",今年" + age + "岁"
// القالب النصي (بسيط)
const message = `我叫${name},今年${age}岁`
// النتيجة: "我叫张三,今年25岁"نقطة التعرف: عندما ترى backtick و ${}، فاعلم أنه يتم إدراج متغيرات في النص.
الكائن = مجموعة من الخصائص المسماة (مثل نموذج معلومات شخصية)
const user = {
name: "张三",
age: 25,
isVIP: true
}
// استخدام النقطة للوصول إلى الخصائص
console.log(user.name) // "张三"
console.log(user.age) // 25المصفوفة = مجموعة من البيانات المرتبة (مثل قائمة)
const colors = ['أحمر', 'أخضر', 'أزرق']
// الوصول بالفهرس (يبدأ من 0)
console.log(colors[0]) // "أحمر"
console.log(colors[1]) // "أخضر"الهياكل المتداخلة: كائنات داخل مصفوفات، مصفوفات داخل كائنات
هذا هو هيكل البيانات الأكثر شيوعًا في كود الذكاء الاصطناعي:
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 منههذه من أكثر المشاكل التي يواجهها المبتدئون!
تعيين الأنواع الأساسية (string، number، boolean) = نسخ بيانات جديدة بالكامل:
let a = 10
let b = a // b يحصل على نسخة من a
b = 20
console.log(a) // 10 (a لم يتأثر)تعيين الكائنات والمصفوفات = نسخ "العنوان" (يشيران إلى نفس الشيء):
let user1 = { name: "张三" }
let user2 = user1 // user2 يشير إلى نفس الكائن
user2.name = "李四" // تعديل user2 سيؤثر على user1
console.log(user1.name) // "李四" (user1 تغير أيضًا!)لماذا ننشئ نسخًا؟
في React/Vue، تعديل البيانات مباشرة يؤدي إلى عدم تحديث الواجهة. لذلك غالبًا ما ترى [...array] أو {...obj} في كود الذكاء الاصطناعي — إنه ينشئ نسخة لتجنب التأثير المتبادل.
// استخدام معامل النشر لإنشاء نسخة
const arr1 = [1, 2, 3]
const arr2 = [...arr1] // إنشاء مصفوفة جديدة
arr2.push(4)
console.log(arr1) // [1, 2, 3] (لم يتأثر)
console.log(arr2) // [1, 2, 3, 4]👇 جرب بنفسك: لاحظ كيف تتغير البيانات الأصلية عند تعديل النسخة
هاتان الصيغتان منتشرتان في كل مكان في كود الذكاء الاصطناعي، إن لم تتعرف عليهما فلن تفهم الكود.
التفكيك (Destructuring): استخراج البيانات بسرعة من الكائنات أو المصفوفات
const user = { name: "张三", age: 25, city: "北京" }
// الطريقة التقليدية (مزعجة)
const name = user.name
const age = user.age
// طريقة التفكيك (بسيطة)
const { name, age } = user
// نفس النتيجة، لكن في سطر واحدمعامل النشر (Spread): نسخ وتوسيع البيانات
// نسخ مصفوفة وإضافة عناصر جديدة
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 → نشر (توسيع) المصفوفة أو الكائن🤔 السؤال الأساسي
كيف "يتخذ الكود قرارات" و"يكرر الأشياء"؟ البرنامج يحتاج إلى تنفيذ عمليات مختلفة حسب الشروط، ويحتاج أيضًا إلى تكرار مهام معينة — كيف يُعبَّر عن هذا المنطق؟
if/else: أبسط أشكال الحكم الشرطي
const age = 18
if (age >= 18) {
console.log("بالغ")
} else {
console.log("قاصر")
}المعامل الثلاثي: اختصار لـ if/else
// الطريقة الكاملة (4 أسطر)
let message
if (age >= 18) {
message = "بالغ"
} else {
message = "قاصر"
}
// المعامل الثلاثي (سطر واحد)
const message = age >= 18 ? "بالغ" : "قاصر"
// الصيغة: الشرط ? القيمة عندما يكون الشرط صحيحًا : القيمة عندما يكون الشرط خاطئًاطريقة الاختصار &&: شائعة في كود React
// فقط عندما يكون isLoggedIn قيمته true، يتم عرض لوحة المستخدم
isLoggedIn && <UserPanel />
// تكافئ
if (isLoggedIn) {
return <UserPanel />
}💡 مهارة التعرف
? : → هذا هو المعامل الثلاثي، اختصار لـ if/else&& → ما قبله true، نفذ ما بعدهالدالة = وصفة طبق
// تعريف الدالة (كتابة الوصفة)
function greet(name) {
return "Hello " + name
}
// استدعاء الدالة (الطهي حسب الوصفة)
console.log(greet("张三")) // "Hello 张三"
console.log(greet("李四")) // "Hello 李四"ثلاث طرق للكتابة، تعرف عليها بنظرة واحدة:
// 1. تعريف function (الطريقة التقليدية)
function greet(name) {
return "Hello " + name
}
// 2. دالة السهم (الأكثر استخدامًا في كود الذكاء الاصطناعي)
const greet = (name) => {
return "Hello " + name
}
// 3. اختصار دالة السهم (عندما يكون هناك سطر واحد فقط)
const greet = (name) => "Hello " + name👇 جرب بنفسك: أدخل أسماء مختلفة لترى كيف تعمل الدالة
💡 مهارة التعرف
function أو => → هذه دالةfn() → يتم استدعاء هذه الدالة() => {} → دالة السهم، الطريقة السائدة في JavaScript الحديثةفي React/Vue، تقريبًا كل عرض قائمة يستخدم هذه الدوال.
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>) → تحويل كل عنصر بيانات إلى وسم قائمةتشبيه "الغرفة":
const global = "متغير عام" // أشياء في الممر
function room() {
const local = "أشياء في الغرفة" // أشياء في الغرفة
console.log(global) // ✅ يمكن رؤية الممر
}
console.log(local) // ❌ خطأ! لا يمكن رؤية الأشياء في الغرفة من الخارجالحدس الأساسي: مكان كتابة الكود يحدد ما يمكنه رؤيته من متغيرات.
👇 جرب بنفسك: انقر على نطاقات مختلفة لترى أي المتغيرات يمكن الوصول إليها
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.
}لا تعتبرها مفهومًا مستقلًا، بل افهمها من خلال سيناريو ملموس:
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الحدس الأساسي: عندما تُنشأ الدالة، فإنها "تتذكر" المتغيرات المحيطة بها، حتى بعد انتهاء تنفيذ الدالة الخارجية.
👇 جرب بنفسك: لاحظ كيف يجعل الإغلاق الدالة "تتذكر" الحالة
لن نشرح قواعد الربط المعقدة، فقط السيناريوهات الأكثر شيوعًا:
السيناريو 1: داخل دوال الكائن، this يشير إلى هذا الكائن
const user = {
name: "张三",
sayHi() {
console.log("مرحبًا، أنا " + this.name) // this يشير إلى user
}
}
user.sayHi() // "مرحبًا، أنا 张三"السيناريو 2: في مراقبة الأحداث، this يشير إلى العنصر الذي أطلق الحدث
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"
🤔 السؤال الأساسي
كيف يتفاعل JavaScript مع صفحة الويب؟ كيف يعثر على العناصر في الصفحة؟ كيف يستجيب لنقرات المستخدم وإدخالاته؟ كيف يحصل على البيانات من الخادم؟
صفحة الويب في عيون JavaScript هي "شجرة"، كل وسم HTML هو "عقدة" في الشجرة.
<html>
<body>
<h1>عنوان</h1>
<p>فقرة</p>
<ul>
<li>عنصر 1</li>
<li>عنصر 2</li>
</ul>
</body>
</html>تحكم JS في صفحة الويب = العثور على العقدة + تعديل العقدة + إنشاء/حذف العقدة
👇 جرب بنفسك: انقر على العقد لترى كيف تنتظم شجرة DOM
Welcome
Click a button above to see the matching codeالبحث عن العناصر:
// البحث باستخدام محددات CSS (الأكثر استخدامًا)
const title = document.querySelector('h1') // ابحث عن أول h1
const button = document.querySelector('#btn') // ابحث عن العنصر ذو id="btn"
const items = document.querySelectorAll('.item') // ابحث عن جميع العناصر ذات class="item"تعديل العناصر:
// تغيير النص
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 → تغيير فئات CSSaddEventListener: إضافة مراقبة الأحداث إلى عنصر
button.addEventListener('click', () => {
console.log("تم النقر على الزر")
})الأحداث الشائعة:
| الحدث | وقت الإطلاق | سيناريو واقعي |
|---|---|---|
click | النقر | النقر على الأزرار، الانتقال بالروابط |
input | تغير محتوى حقل الإدخال | البحث الفوري، التحقق من النماذج |
submit | إرسال النموذج | تسجيل الدخول، التسجيل، إرسال البيانات |
scroll | تمرير الصفحة | التحميل الكسول، العودة إلى الأعلى |
كائن الحدث: الحصول على مزيد من المعلومات
input.addEventListener('input', (e) => {
console.log(e.target.value) // الحصول على قيمة حقل الإدخال
e.preventDefault() // منع السلوك الافتراضي (مثل تحديث الصفحة بعد إرسال النموذج)
})💡 تطبيق عملي
عندما تريد إضافة وظيفة إلى زر، فأنت في الأساس تخبر الذكاء الاصطناعي: "أضف حدث نقرة إلى هذا الزر، وعند النقر نفذ عملية كذا"
تشبيه المطعم:
بعد طلب الطعام، لا تحتاج إلى الوقوف عند باب المطبخ منتظرًا، يمكنك فعل أشياء أخرى، وعندما يصبح الطعام جاهزًا سيحضره النادل.
السيناريو الأكثر شيوعًا: جلب البيانات من الخادم
// الطريقة المتزامنة (ستجمد الصفحة، لا تستخدمها)
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 → معالجة الأخطاء المحتملةبدون مصطلحات "المهام الدقيقة/المهام الكبيرة"، استخدم نموذجًا بسيطًا للفهم:
JS هي "محطة عمل فردية"، تفعل شيئًا واحدًا فقط في كل مرة، لكن لديها "لوحة مهام ورقية" (طابور المهام).
عند مواجهة عملية تحتاج إلى انتظار (طلب شبكة، مؤقت)، لا تنتظر JS بغباء، بل تضع "ماذا تفعل بعد انتهاء الانتظار" على اللوحة، وتستمر في التنفيذ. وعندما تنتهي من العمل الحالي، تذهب لتفقد اللوحة.
console.log("1")
setTimeout(() => console.log("2"), 0) // حتى لو كانت 0 ثانية، سيتم التأجيل
console.log("3")
// الناتج: 1, 3, 2 (وليس 1, 2, 3!)لماذا؟
console.log("1") → إخراج 1setTimeout → وضع دالة الرد على اللوحة، والمتابعةconsole.log("3") → إخراج 3setTimeout → إخراج 2👇 جرب بنفسك: لاحظ ترتيب تنفيذ الكود
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، وانتظر حتى تصل البيانات ثم اعرضها"
أول سطر في كود React/Vue الذي ينشئه الذكاء الاصطناعي يكون دائمًا تقريبًا import.
import = استيراد وظائف من ملف آخر
// استيراد دالة من ملف أدوات
import { formatDate } from './utils'
// استيراد من حزمة خارجية
import React from 'react'
import { useState } from 'react'export = تصدير الوظائف ليستخدمها الآخرون
// utils.js
export function formatDate(date) {
// ...
}
// أو تصدير افتراضي
export default function formatDate(date) {
// ...
}حزمة npm = أدوات كتبها آخرون، يمكنك استخدامها بعد التثبيت
// تثبيت الحزمة: npm install lodash
// استخدام الحزمة
import _ from 'lodash'💡 مهارة التعرف
import → استيراد وظائف من ملف آخرexport → تصدير الوظائف ليستخدمها الآخرونfrom 'react' → استيراد من حزمة Reactfrom './utils' → استيراد من ملف محلي🤔 السؤال الأساسي
تعلمت كل هذه الصيغ، كيف تستخدمها فعليًا عندما تحصل على كود من الذكاء الاصطناعي؟ كيف تقرأ الكود بسرعة؟ ماذا تفعل عند مواجهة خطأ؟ كيف تجعل الذكاء الاصطناعي يعدل الكود بدقة؟
طريقة الخطوات الأربع:
| الخطوة | ماذا تنظر | مثال |
|---|---|---|
| الخطوة الأولى: انظر إلى الهيكل العام | كم عدد الدوال؟ ماذا تفعل كل منها؟ | loadData() تحميل البيانات، renderList() عرض القائمة |
| الخطوة الثانية: ابحث عن نقطة الدخول | من أين يبدأ تنفيذ البرنامج؟ | addEventListener('click', ...) يبدأ عند النقر |
| الخطوة الثالثة: تتبع تدفق البيانات | من أين تأتي البيانات؟ إلى أين تذهب؟ | من API → تحليل → عرض على الصفحة |
| الخطوة الرابعة: انظر إلى المنطق التفصيلي | كيف تعالج الدوال المحددة؟ | حلقات، شروط، حسابات |
استخدام مثال الكود من الفصل 1 لعمل "عرض قراءة" كامل:
// الخطوة الأولى: الهيكل العام
// - مصفوفة ألوان
// - متغير لتسجيل الفهرس الحالي
// - حدث نقرة على زر
// الخطوة الثانية: نقطة الدخول
// button.addEventListener('click', ...) → ينفذ عند النقر على الزر
// الخطوة الثالثة: تدفق البيانات
// colors (مصفوفة الألوان) → currentIndex (الفهرس الحالي) → backgroundColor (لون الخلفية)
// الخطوة الرابعة: المنطق التفصيلي
// currentIndex = (currentIndex + 1) % colors.length
// معنى هذه الصيغة: زيادة 1 في كل مرة، لكن لا تتجاوز طول المصفوفة (دوري)| الخطأ | شرح مبسط | ماذا تقول للذكاء الاصطناعي |
|---|---|---|
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، تحقق من صحة عنوان الواجهة" |
الفرق بين المطور المبتدئ والمتمرس غالبًا ما يظهر في دقة وصف المشكلة.
| ❌ وصف سيء | ✅ وصف جيد |
|---|---|
| "الكود فيه خطأ" | "عند النقر على زر الحذف، يحذف العنصر الأخير بدلًا من العنصر الحالي" |
| "التنسيق غير صحيح" | "العنوان يجب أن يكون في المنتصف، لكنه حاليًا بمحاذاة اليسار" |
| "البيانات لا تظهر" | "طلب fetch أعاد البيانات (يمكن رؤيتها في وحدة التحكم)، لكن الصفحة لم تُعِد العرض" |
| "أضف وظيفة" | "أضف مربع بحث في صفحة قائمة المستخدمين، يُصفي القائمة فوريًا أثناء الكتابة، مع مطابقة تقريبية حسب حقل name" |
| "النقر لا يفعل شيئًا" | "عند النقر على الزر، تظهر في وحدة التحكم رسالة خطأ 'Cannot read property of undefined'، الخطأ في السطر X" |
تمرين عملي:
// كود به خطأ
function deleteTodo(index) {
todos.splice(index, 1) // دائمًا يحذف العنصر الأخير
}
// الظاهرة الخاطئة: أيًا كان زر الحذف الذي تنقر عليه، يُحذف العنصر الأخير دائمًا❌ وصف سيء: "وظيفة الحذف فيها خطأ"
✅ وصف جيد: "عند النقر على زر الحذف، لا يحذف العنصر الحالي بل يحذف العنصر الأخير. الكود يستخدم splice(index, 1)، لكن index قد لا يكون صحيحًا. يحتاج إلى التعديل ليستخدم id الفريد لكل عنصر للحذف المطابق."
const/let → معرفة ما إذا كان يمكن إعادة تعيين المتغير{} → كائن / رؤية [] → مصفوفة{...obj} أو [...arr] → إنشاء نسخةfunction أو => → تعريف عملية قابلة للتكرارif/else أو ? : → الكود يقوم بحكم شرطي.map() / .filter() → تحويل أو تصفية مصفوفةdocument.querySelector → البحث عن عنصر في صفحة الويبaddEventListener → مراقبة عمليات المستخدمasync/await → انتظار عملية تستغرق وقتًاimport/export → استيراد أو تصدير وحداتإذا قرأت بعناية أقسام "التعمق" في كل فصل، فأنت أيضًا تتقن هذه المفاهيم الأساسية:
هذه المفاهيم ستساعدك في تحديد المشاكل بشكل أسرع.
💡 عند مواجهة مشكلة، قل هذا للذكاء الاصطناعي