Hoisting والـ TDZ — ليه var بتقول undefined وlet بتنفجر؟
ليه الدرس ده؟ "اشرح الـ hoisting" سؤال شبه مضمون في أي انترفيو JS — وأغلب الإجابات الغلط سببها حفظ قاعدة بدل فهم مرحلة الإنشاء اللي شفتها بعينك في درس 0001.
🔁 مراجعة سريعة قبل ما تبدأ (~5 دقايق):
- ورقة نموذج التنفيذ — ركز على المصطلحات والقواعد الذهبية (بتفتح في تاب جديد)
- اسأل نفسك من الذاكرة: إيه اللي بيحصل في مرحلة الإنشاء؟ — لو الإجابة طلعت بسهولة، ادخل على الدرس. لو لأ، ارجع لمحاكي درس 0001 دقيقتين
١ — الفكرة في 3 جمل
① فاكر مرحلة الإنشاء من درس 0001؟ قبل تنفيذ أي سطر، المحرك بيمسح الكود وبيسجل كل التعريفات في الـ execution context — ده هو الـ Hoisting (الرفع): مش إن الكود "بيتحرك لفوق"، لكن إن التسجيل بيحصل قبل التنفيذ.
② الفرق كله في حالة المتغير وقت التسجيل: var بتتسجل بقيمة مبدئية undefined، وfunction declaration بتتسجل كاملة جاهزة للنداء، أما let/const بيتسجلوا من غير قيمة خالص.
③ الفترة من بداية الـ scope لحد سطر تعريف let/const اسمها TDZ = Temporal Dead Zone (المنطقة الميتة المؤقتة): المتغير محجوز لكن أي لمسة ليه = ReferenceError فوري.
٢ — شوفها بعينك: محاكي مرحلة الإنشاء
نفس محاكي درس 0001 بس النجم هنا هو جوه الـ Global context. سيناريوهين متضادين — وده مقصود: وبضدها تستبين الأشياء. توقع قبل كل خطوة!
console.log(a); sayHi(); var a = 1; console.log(a); function sayHi() { console.log("hi"); }
٣ — المقارنة اللي بتتسأل في الانترفيوهات
var | let / const | function declaration | |
|---|---|---|---|
| بتتسجل في مرحلة الإنشاء؟ | أيوه | أيوه (لكن!) | أيوه |
| قيمتها وقت التسجيل | undefined | ⏳ من غير قيمة (TDZ) | الدالة كاملة ✓ |
| الوصول ليها قبل سطرها | بيرجع undefined | 💥 ReferenceError | بتشتغل عادي |
✓ كل صف في الجدول ده متحقق منه بتشغيل حقيقي بـ Node.js على جهازك (2026-08-03) — مش منقول من مقالات.
سؤال الـ judgment (فكرة السينيور): طب ليه صمموا let/const كده؟ لأن سلوك var بيخبي البجز: كودك بيشتغل بقيمة undefined غلط في صمت. الـ TDZ بتقلب الغلطة الصامتة لخطأ صريح بيصرخ مكان ما حصل — وده تحسين، مش تعقيد. علشان كده القاعدة العملية: const افتراضياً، let لو هتعيد الإسناد، وvar مالهاش مكان في كود جديد.
٤ — الفخ الشهير: function declaration ضد function expression
sayHi(); // ✓ "hi"
function sayHi() { console.log("hi"); }
foo(); // 💥 TypeError: foo is not a function
var foo = function() {};
فكّر بمرحلة الإنشاء: foo اتسجلت كـ var عادية بقيمة undefined — الدالة نفسها مش هتتحط فيها غير لما سطرها يتنفذ. فلما نديت عليها بدري، أنت فعلياً كتبت undefined() — وده TypeError (النوع غلط) مش ReferenceError (الاسم موجود أصلاً!). ✓ متحقق منه بالتشغيل
٥ — توقع قبل ما تشوف (3 تمارين)
اقرا السنيبت، وقرر: إيه اللي هيحصل؟ ماتجربش في الـ console قبل ما تجاوب هنا.
console.log(x); var x = 5;
console.log(y); let y = 5;
hello();
function hello() { console.log("أهلاً"); }
٦ — اختبر نفسك
س1: في مرحلة الإنشاء، متغير var بياخد إيه؟
س2: TDZ (Temporal Dead Zone) معناها بالنسبة لمتغير let:
س3 (سؤال judgment): ليه المحترفين بيبدأوا بـ const مش var؟
س4: foo(); وبعدها var foo = function(){}; — النتيجة؟
٧ — التحدي الأخير: اشرحها بصوت عالي
ده تمرين "explain" بتاع الأسبوع من الـ roadmap نفسه. من غير ما تبص على أي حاجة:
"خد السنيبت ده واشرح ترتيب التنفيذ وليه كل سطر بيطلّع اللي بيطلّعه:"
console.log(city); console.log(country); var city = "القاهرة"; let country = "مصر";
الإجابة الكاملة المفروض تمر على: مرحلة الإنشاء (مين اتسجل بإيه) → السطر الأول (undefined وليه) → السطر التاني (ReferenceError وليه البرنامج وقف هنا أصلاً). لو عديتها بسلاسة، يبقى مهمتين "explain" بتوع الأسبوع الأول اتقفلوا مع بعض.
٨ — المصدر الأساسي للتعمق
- MDN — Hoisting — التعريف المرجعي + أنواع الـ hoisting الأربعة (اتحققت منه live قبل بناء الدرس).
- javascript.info — The old "var" — ليه var مختلفة وليه بطّلنا نستخدمها.
- ورقة المراجعة: reference/js-execution-model.html (اتضاف فيها قسم الـ hoisting)