Execution Context والـ Call Stack — إزاي JS بيشغّل كودك فعلاً
ليه الدرس ده؟ ده أول سؤال بيفرّق بين "بستخدم JS" و"فاهم JS" في أي انترفيو محترم — وهو الأساس اللي هيتبني عليه فهمك لـ hoisting والـ closures والـ event loop في الأسابيع الجاية إن شاء الله.
🔁 قبل ما تبدأ: ده أول درس في الرحلة — مفيش prerequisites غير أساسيات JS اللي معاك من شغلك. ادخل على طول.
📖 لو سألتك: "إيه هو الـ Execution Context؟"
الـ Execution Context هو البيئة اللي الـ JavaScript engine بيجهزها لأي كود قبل ما ينفذه — فيها المتغيرات والـ scope وقيمة this. وبيتعمل واحد Global (للملف كله) وواحد جديد مع كل نداء function. والـ Call Stack هو البنية اللي بتتراكم فيها الـ execution contexts دي فوق بعض وقت التنفيذ، بترتيب LIFO (Last In, First Out: آخر واحد دخل هو أول واحد يخرج).
١ — الفكرة في 3 جمل
① كل ما JS يبدأ يشغّل كود، بيعمل حاجة اسمها Execution Context — "بيئة تنفيذ" فيها كل اللي الكود محتاجه (المتغيرات، الـ scope، قيمة this).
② أول ما البرنامج يبدأ بيتعمل Global Execution Context واحد، وكل استدعاء لأي function بيعمل execution context جديد خاص بيها.
③ الـ contexts دي بتترص فوق بعض في Call Stack: اللي بيتنفذ دلوقتي هو اللي فوق خالص، ولما يخلّص بيتشال — آخر واحد دخل، أول واحد يخرج (ودي اللي بيسموها LIFO = Last In, First Out).
٢ — كل context بيتعمل على مرحلتين
دي النقطة اللي أغلب الجونيورز مش واخدين بالهم منها، وهي مفتاح فهم الـ hoisting (درسنا الجاي إن شاء الله):
مرحلة الإنشاء (Creation): قبل تنفيذ أي سطر، المحرك بيمسح الكود وبيحجز مكان للمتغيرات والدوال في الذاكرة.
مرحلة التنفيذ (Execution): الكود بيتنفذ سطر سطر والقيم بتتحط في الأماكن المحجوزة.
خد بالك: وجود المرحلتين دول هو السبب الحقيقي إن var بتظهر بقيمة undefined قبل سطر تعريفها. هنشرّح ده في درس 0002 إن شاء الله.
٣ — شوفها بعينك: محاكي الـ Call Stack
الكود ده هنمشيه سطر سطر. دوس «خطوة» وراقب حاجتين مع بعض: الـ Call Stack من بره (مين داخل ومين خارج)، وجوه كل context — المتغيرات وقيمها بتتغير لحظة بلحظة (الأصفر = اتغير حالاً، ⏳ = محجوز في مرحلة الإنشاء ولسه ماخدش قيمة). وحاول تتوقع قبل كل ضغطة إيه اللي هيحصل:
function greet(name) { const msg = build(name); console.log(msg); } function build(name) { return "أهلاً يا " + name; } greet("عمر");
٤ — Stack Overflow مش بس اسم موقع
الـ stack ليه حجم محدود. لو function فضلت تنادي نفسها من غير نقطة توقف، الـ frames هتتراكم لحد ما المساحة تخلص — وده الخطأ الشهير:
function boom() { boom(); }
boom(); // RangeError: Maximum call stack size exceeded
لما تشوف الرسالة دي في شغلك، دلوقتي بقيت عارف معناها الحرفي: الـ call stack اتملى عن آخره.
٥ — اختبر نفسك (من غير ما ترجع فوق!)
المحاولة من الذاكرة هي اللي بتثبّت المعلومة — جاوب الأول، وبعدين هتاخد التصحيح فوراً.
س1: الـ Call Stack بيشتغل بأي نظام؟
س2: (بعيداً عن الـ Global context اللي بيتعمل مرة واحدة عند تحميل السكريبت) — امتى بيتعمل Execution Context جديد لدالة؟
س3: إيه اللي هيتطبع من الكود ده بالترتيب؟
function a() {
console.log(1);
b();
console.log(3);
}
function b() { console.log(2); }
a();
س4: في المحاكي فوق، لحظة تنفيذ سطر return "أهلاً يا " + name — كام context موجود في الـ stack؟
٦ — التحدي الأخير: اشرحها بصوت عالي
ده تمرين من الـ roadmap بتاعك نفسه (مهمة "explain"). اقفل الصفحة دي، وسجّل صوتك أو اشرح لحد قدامك:
"لما بكتب myFunction() في JS — إيه اللي بيحصل بالظبط من اللحظة دي لحد ما السطر اللي بعديها يشتغل؟"
الإجابة الكاملة المفروض تلمس: إنشاء context جديد → دخوله الـ stack → التنفيذ → خروجه من الـ stack → الرجوع للـ context اللي تحتيه. لو اتلخبطت في أي جزء، ده بالظبط الجزء اللي ترجع تراجعه.
٧ — المصدر الأساسي للتعمق
اقرأ النص ده (15-20 دقيقة) لتثبيت الدرس — أفضل شرح مكتوب مجاني للموضوع:
- javascript.info — Recursion and stack — اقرأ جزء "The execution context and stack" بالذات.
- MDN — Call Stack — التعريف المرجعي الرسمي.
- ورقة المراجعة السريعة: reference/js-execution-model.html