هندسة جافا سكريبت المتقدمة 🚀

من الأساسيات إلى الاحتراف المعياري (Standard JS)

1. كيف تكتب دالة احترافية؟ (The Perfect Function)

الدالة ليست مجرد كود ينفذ مهمة، بل هي "عقد" بينك وبين البرنامج. المبرمج المحترف يراعي ثلاثة أشياء:

أ. الوسائط الافتراضية (Default Parameters)

تمنع انهيار البرنامج إذا نسي المستخدم إدخال قيمة.

function greetUser(name = "ضيفنا العزيز") {
  return `أهلاً بك، ${name}`;
}

ب. الدوال السهمية (Arrow Functions)

طريقة مختصرة وحديثة، وهي الأساس في أطر العمل مثل React. تتميز بأنها لا تملك this خاص بها.

const calculateTotal = (price, tax) => price + tax;

ج. الدوال المجهولة (Anonymous Functions)

تستخدم كـ "عمال مؤقتين" داخل دوال أخرى (Callbacks).

2. أين يعيش المتغير؟ (Scope & Closures)

الـ Scope: هو الحدود التي يعيش فيها المتغير. إذا عرفت متغير داخل دالة، لا يمكنك رؤيته من الخارج.

مفهوم الـ Closure (الإغلاق):

هو قدرة الدالة "الداخلية" على تذكر متغيرات الدالة "الخارجية" حتى بعد أن تنتهي الدالة الخارجية من العمل. هذا هو سر حماية البيانات في JS.

function createCounter() {
  let count = 0; // متغير محمي
  return function() {
    count++;
    return count;
  };
}
const counter = createCounter();
console.log(counter()); // 1

3. البرمجة كائنية التوجه (Classes & OOP)

هذا المفهوم يسمح لك بصناعة "قوالب" منظمة بدلاً من كتابة كود عشوائي (Spaghetti Code).

تخيل الـ **Class** كأنه "رسم هندسي" لسيارة، والـ **Object** هو "السيارة الحقيقية" التي خرجت من المصنع بناءً على الرسم.

4. فن الدفاع عن الكود (Try...Catch)

المبرمج العظيم يتوقع الخطأ قبل وقوعه. نستخدم try لتجربة كود قد يفشل، و catch للإمساك بالخطأ ومعالجته دون أن يتوقف الموقع.

try {
  fetchDataFromServer();
} catch (error) {
  console.error("حدث خطأ في الاتصال بالسيرفر: " + error.message);
}

5. فن التفكيك (Destructuring & Spread)

بدلاً من استخراج البيانات من المصفوفات أو الكائنات يدوياً في أسطر كثيرة، نستخدم "التفكيك" للحصول عليها في سطر واحد.

الميزة: كود أنظف وأقل عرضة للأخطاء
const game = { title: "War Tycoon", price: 0, platform: "Roblox" };

// الطريقة القديمة:
// let title = game.title;

// الطريقة الاحترافية (Destructuring):
const { title, price } = game;
console.log(title); // War Tycoon

معامل الانتشار (Spread Operator `...`):

يستخدم لنسخ المصفوفات أو دمجها بسهولة تامة دون التأثير على الأصل.

const oldGames = ["Minecraft", "Roblox"];
const allGames = [...oldGames, "FIFA 26"]; // دمج ونسخ في خطوة واحدة

6. هندسة الوحدات (ES6 Modules)

في المشاريع الحقيقية، لا نضع 1000 سطر في ملف واحد. نقوم بتقسيم الكود إلى ملفات صغيرة (Modules).

- Export: تستخدمها في الملف الذي "يحتوي" على الدالة لكي تسمح للآخرين باستخدامها.
- Import: تستخدمها في الملف الذي "يريد" استخدام تلك الدالة.
// في ملف math.js
export const add = (a, b) => a + b;

// في ملف main.js
import { add } from './math.js';

7. الذاكرة المحلية (LocalStorage & SessionStorage)

كيف تجعل المتصفح "يتذكر" خيارات المستخدم حتى بعد إغلاق الصفحة؟

- LocalStorage: تخزين دائم لا يُمسح إلا يدوياً (مثالي لحفظ الـ High Score أو الـ Theme).
- SessionStorage: تخزين مؤقت يُمسح بمجرد إغلاق التبويب (Tab).
// حفظ بيانات
localStorage.setItem('username', 'AMG');

// جلب بيانات
const user = localStorage.getItem('username');

ملاحظة: الـ LocalStorage يحفظ النصوص فقط، لذا نستخدم JSON.stringify لحفظ المصفوفات.

8. التحكم في الزمن (SetTimeout & SetInterval)

أحياناً نريد تنفيذ كود بعد وقت معين، أو تكراره كل ثانية (مثل ساعة الموقع أو مؤقت اللعبة).

// تنفيذ مرة واحدة بعد 3 ثوانٍ
setTimeout(() => {
  console.log("انتهى الوقت!");
}, 3000);

// تكرار كل ثانية
setInterval(() => {
  console.log("ثانية مرت...");
}, 1000);

9. التعبيرات النمطية (Regular Expressions - Regex)

تعتبر الـ Regex هي "لغة البحث داخل النصوص". تستخدم للتأكد من أن البيانات المدخلة (مثل الإيميل أو رقم الهاتف) تتبع نمطاً صحيحاً قبل إرسالها للسيرفر.

لماذا نستخدمها؟
- التأكد من قوة كلمة المرور.
- البحث عن كلمات معينة واستبدالها في نصوص ضخمة.
- استخراج أرقام الهواتف من بين آلاف السطور.
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const myEmail = "AMG@phinex.com";

console.log(emailPattern.test(myEmail)); // true (الإيميل صحيح)

10. هندسة الأداء (Debounce & Throttle)

تخيل أنك تبني نظام بحث؛ لو قمت بإرسال طلب للسيرفر مع كل حرف يكتبه المستخدم، ستنهار قاعدة البيانات! هنا نستخدم تقنيات "التهدئة".

- Debounce: انتظر حتى يتوقف المستخدم عن الكتابة تماماً لمدة (مثلاً 500ms) ثم نفذ الأمر.
- Throttle: نفذ الأمر مرة واحدة فقط كل (مثلاً ثانية) مهما حاول المستخدم الضغط على الزر بسرعة.

مثال الـ Debounce (احترافي):

let timer;
input.addEventListener('keyup', () => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    console.log("تم إرسال طلب البحث للسيرفر...");
  }, 500);
});

11. الأدوات السرية (Symbols & Generators)

هذه الأدوات تُستخدم لبناء مكتبات (Libraries) أو أنظمة معقدة تحتاج لخصوصية عالية أو تحكم في تدفق البيانات.

function* numberGenerator() {
  yield 1;
  yield 2;
  return 3;
}
const gen = numberGenerator();
console.log(gen.next().value); // 1

12. فلسفة الكود النظيف (Clean Code)

في PhineX، لا نكتب كوداً يعمل فحسب، بل نكتب كوداً يستطيع الآخرون قراءته وتطويره بعدنا.

قواعد ذهبية:
1. تجنب الأرقام السحرية: لا تكتب if(x === 86400) بل عرف متغيراً const SECONDS_IN_DAY = 86400.
2. وظيفة واحدة لكل دالة: الدالة التي تحسب السعر يجب ألا تقوم بتغيير لون الزر!
3. الأسماء الوصفية: استخدم gamePrice بدلاً من gp.

اختبار المحترف 🧠

س1: ماذا يحدث للمتغير المرفق بـ let داخل دالة عند استدعائه من خارجها؟



س2: ما هي فائدة الـ constructor داخل الـ Class؟



س3: في الـ Arrow Function، هل يمكننا استخدام الكلمة المفتاحية function؟



س4: ماذا يفعل الـ Spread Operator `...` عند استخدامه مع مصفوفة؟



س5: أي من التالي يُمسح تلقائياً عند إغلاق المتصفح؟