← الدرس السابق المستوى 3 - الدرس 5 من 10

⚙️ الدوال (Functions) في JavaScript: الدليل الشامل

تعلم كيف تُنشئ كود قابل لإعادة الاستخدام باستخدام الدوال التقليدية والسهمية

تقدمك في المستوى الثالث 50%

📋 محتويات الدرس

  1. ما هي الدوال ولماذا نحتاجها؟
  2. تعريف الدالة — Function Declaration
  3. المعاملات (Parameters) والوسائط (Arguments)
  4. return — إرجاع القيم وإيقاف الدالة
  5. Function Expression و Anonymous Functions
  6. Arrow Functions — الدوال السهمية الحديثة
  7. القيم الافتراضية للمعاملات
  8. نطاق المتغيرات (Scope) داخل الدوال
  9. Callback Functions — الدوال كمعاملات
  10. Higher-Order Functions — دوال من الدرجة الأولى
  11. أمثلة واقعية من التطبيقات
  12. اختبر فهمك — اختبار تفاعلي

📖 ما هي الدوال ولماذا نحتاجها؟

الدالة (Function) هي كتلة من الكود المُسمّاة يمكن استدعاؤها عدة مرات. بدلاً من كتابة نفس الكود 10 مرات، تكتبه مرة واحدة في دالة وتستدعيها 10 مرات.

💡 لماذا الدوال مهمة جداً؟
  • 🔄 إعادة الاستخدام: اكتب مرة واحدة، استخدم ألف مرة
  • 🧹 التنظيم: تقسيم الكود الكبير لقطع صغيرة مفهومة
  • 🐛 سهولة التصحيح: إذا فيه خطأ، تصلحه في مكان واحد
  • 🤝 التعاون: مطورون مختلفون يعملون على دوال مختلفة
  • 📦 التجريد (Abstraction): تخفي التعقيد وتُظهر الواجهة البسيطة

مثال من الحياة: تخيل إنك بتعمل "سندويتش". بدلاً ما تشرح كل خطوة كل مرة (خبز، جبنة، لحمة، خس، خبز)، تقول ببساطة "اعمل سندويتش". الدالة هي "اعمل سندويتش" — تخفي التفاصيل وتُبسّط الاستخدام.

🎯 تعريف الدالة — Function Declaration

أبسط طريقة لتعريف دالة في JavaScript. تبدأ بكلمة function متبوعة بالاسم:

// تعريف الدالة function sayHello() { console.log("مرحباً بالعالم!"); } // استدعاء الدالة (Calling/Invoking) sayHello(); // "مرحباً بالعالم!" sayHello(); // "مرحباً بالعالم!" sayHello(); // "مرحباً بالعالم!"

خصائص Function Declaration

  • Hoisting: يمكن استدعاؤها قبل تعريفها في الكود
  • اسم واضح: يسهل تصحيح الأخطاء (Stack Trace)
  • نطاق عام (Global): متاحة في كل مكان في الملف
// Hoisting: يمكن استدعاؤها قبل التعريف greet("أحمد"); // ✓ يعمل! function greet(name) { console.log(`أهلاً ${name}`); }

📥 المعاملات (Parameters) والوسائط (Arguments)

المعاملات (Parameters) هي المتغيرات التي تُعرّفها في الدالة. الوسائط (Arguments) هي القيم الفعلية التي تُمرّرها عند الاستدعاء.

// name و age هما Parameters function greet(name, age) { console.log(`أهلاً ${name}، عمرك ${age} سنة`); } // "أحمد" و 25 هما Arguments greet("أحمد", 25); // "أهلاً أحمد، عمرك 25 سنة" greet("سارة", 30); // "أهلاً سارة، عمرك 30 سنة"

عدد متغير من الوسائط — arguments object

function sumAll() { let total = 0; for (let num of arguments) { total += num; } return total; } console.log(sumAll(1, 2, 3)); // 6 console.log(sumAll(10, 20)); // 30
⚠️ ملاحظة:

في JavaScript الحديثة، استخدم Rest Parameters ...args بدلاً من arguments — أنظف وأكثر مرونة.

↩️ return — إرجاع القيم وإيقاف الدالة

return يُستخدم لإرجاع قيمة من الدالة إلى المكان الذي استُدعيت منه. كما أنه يوقف تنفيذ الدالة فوراً — أي كود بعد return لن يُنفّذ.

// دالة تجمع رقمين وتُرجع النتيجة function add(a, b) { return a + b; } let result = add(5, 3); console.log(result); // 8 // return يوقف الدالة فوراً function checkAge(age) { if (age < 18) { return "❌ قاصر"; // يتوقف هنا إذا age < 18 } return "✅ بالغ"; // يصل هنا فقط إذا age >= 18 } console.log(checkAge(15)); // "❌ قاصر" console.log(checkAge(25)); // "✅ بالغ"
❌ خطأ شائع:

لا تضع سطر جديد بعد return بدون أقواس — JavaScript تُضيف فاصلة منقوطة تلقائياً!

return
  a + b; // ✗ يرجع undefined!

📝 Function Expression و Anonymous Functions

بدلاً من تعريف الدالة باسم، يمكنك تخزينها في متغير. هذه Function Expression:

// Function Expression const multiply = function(a, b) { return a * b; }; console.log(multiply(4, 5)); // 20 // Anonymous Function — دالة بلا اسم const greet = function(name) { console.log(`أهلاً ${name}`); };

الفرق بين Declaration و Expression

الخاصية Function Declaration Function Expression
Hoisting ✓ نعم ✗ لا
الاسم إلزامي اختياري (anonymous)
متى تستخدم الدوال العامة الدوال المُمررة كمعاملات

⚡ Arrow Functions — الدوال السهمية الحديثة

أضيفت في ES6 (2015). صيغة مختصرة وأكثر وضوحاً للدوال البسيطة. خاصة مفيدة للـ Callbacks.

التطور من القديم للحديث

// 1. Function Declaration (القديم) function multiply(x) { return x * 2; } // 2. Function Expression const multiply = function(x) { return x * 2; }; // 3. Arrow Function (كامل) const multiply = (x) => { return x * 2; }; // 4. Arrow Function (مختصر — سطر واحد) const multiply = x => x * 2; // أمثلة مختصرة const add = (a, b) => a + b; const square = x => x * x; const greet = () => "مرحباً!";

قواعد اختصار Arrow Functions

الحالة الصيغة مثال
معامل واحد بدون أقواس x => x * 2
معاملات متعددة أو صفر مع أقواس (a, b) => a + b
سطر واحد + return بدون أقواس متعرجة و return x => x * x
❌ لا تستخدم Arrow Functions إذا:
  • تحتاج this — Arrow Functions لا تملك this خاص بها
  • تحتاج arguments object — غير متاح
  • تُستخدم كـ Constructor (مع new) — لا يمكن

🎯 القيم الافتراضية للمعاملات

يمكنك تحديد قيمة افتراضية للمعامل. إذا لم يُمرّر الوسيط، تُستخدم القيمة الافتراضية:

// قيمة افتراضية بسيطة function greet(name = "زائر") { console.log(`أهلاً ${name}`); } greet(); // "أهلاً زائر" greet("علي"); // "أهلاً علي" // قيمة افتراضية معقدة function createUser(name, role = "user", isActive = true) { return { name, role, isActive }; } console.log(createUser("أحمد")); // { name: "أحمد", role: "user", isActive: true } console.log(createUser("سارة", "admin")); // { name: "سارة", role: "admin", isActive: true }

🔒 نطاق المتغيرات (Scope) داخل الدوال

المتغيرات المُعلنة داخل دالة لا يمكن الوصول إليها من خارجها. هذا يسمى Function Scope:

function calculate() { let result = 42; // متغير محلي console.log(result); // ✓ يعمل داخل الدالة } calculate(); // console.log(result); // ✗ خطأ! result غير معرف خارج الدالة

Closure — إغلاق النطاق

الدوال الداخلية يمكنها الوصول لمتغيرات الدالة الخارجية:

function outer() { let count = 0; function inner() { count++; // ✓ يمكن الوصول لـ count return count; } return inner; } const counter = outer(); console.log(counter()); // 1 console.log(counter()); // 2 console.log(counter()); // 3

🔄 Callback Functions — الدوال كمعاملات

في JavaScript، الدوال هي قيم من الدرجة الأولى (First-Class Citizens) — يمكن تمريرها كمعاملات، وتخزينها في متغيرات، وإرجاعها من دوال أخرى.

// دالة تستقبل دالة أخرى كمعامل function doSomething(callback) { console.log("أعمل شيئاً..."); callback(); // استدعاء الدالة المُمررة } // تمرير Anonymous Function كـ Callback doSomething(() => { console.log("✅ تم الانتهاء!"); }); // مثال عملي: forEach let fruits = ["تفاح", "موز", "برتقال"]; fruits.forEach((fruit, index) => { console.log(`${index + 1}. ${fruit}`); });

🏆 Higher-Order Functions — دوال من الدرجة الأولى

دوال تأخذ دوالاً كمعاملات أو تُرجع دوالاً. هذه أساس البرمجة الوظيفية في JavaScript:

let numbers = [1, 2, 3, 4, 5]; // map — تحويل كل عنصر let doubled = numbers.map(n => n * 2); console.log(doubled); // [2, 4, 6, 8, 10] // filter — تصفية العناصر let evens = numbers.filter(n => n % 2 === 0); console.log(evens); // [2, 4] // reduce — تجميع القيم let sum = numbers.reduce((total, n) => total + n, 0); console.log(sum); // 15

💼 أمثلة واقعية من التطبيقات

1. التحقق من صحة البريد الإلكتروني

function isValidEmail(email) { if (!email || !email.includes("@")) { return false; } const parts = email.split("@"); return parts.length === 2 && parts[1].includes("."); } console.log(isValidEmail("user@example.com")); // true console.log(isValidEmail("invalid")); // false

2. تنسيق السعر مع العملة

function formatPrice(price, currency = "EGP") { const symbols = { EGP: "ج.م", USD: "$", EUR: "€" }; return `${price.toLocaleString()} ${symbols[currency] || currency}`; } console.log(formatPrice(1500)); // "1,500 ج.م" console.log(formatPrice(99.99, "USD")); // "99.99 $"

3. حساب الخصم الديناميكي

function calculateDiscount(price, quantity) { let discount = 0; if (quantity >= 10) discount = 0.2; // 20% else if (quantity >= 5) discount = 0.1; // 10% else if (quantity >= 3) discount = 0.05; // 5% const finalPrice = price * quantity * (1 - discount); return { original: price * quantity, discount: discount * 100 + "%", final: finalPrice.toFixed(2) }; } console.log(calculateDiscount(100, 12)); // { original: 1200, discount: "20%", final: "960.00" }

🚀 الخطوة التالية: المصفوفات المتقدمة

في الدرس السادس، ستتعلم:

  • 📦 Methods المصفوفات: push, pop, shift, unshift, splice
  • 🔍 البحث: find, findIndex, includes
  • 🔄 التحويل: map, filter, reduce بعمق
  • 📊 الفرز: sort مع compare functions
📚 مصادر إضافية:
← الدرس السابق: الحلقات