المرحلة 0 · الأسبوع 1 · الدرس 0003 · ~40 دقيقة

Scope وسلسلة البحث — مين يشوف مين؟

ليه الدرس ده؟ الـ Scope هو آخر قطعة في أساس الأسبوع الأول — ومن غيره الـ Closures (أهم موضوع في المرحلة كلها حسب roadmap بتاعك) هيبقى طلاسم. وهو كمان مصدر باجات يومية حقيقية في الشغل.

🔁 مراجعة سريعة قبل ما تبدأ (~5 دقايق):

١ — الفكرة في 3 جمل

① الـ Scope (النطاق) = المنطقة من الكود اللي المتغير مرئي جواها. في JS الحديثة فيه 3 أنواع: Global (الملف كله)، Function (جوه الدالة)، Block (جوه أي { } — زي if وfor).

② الـ scopes بتتداخل زي الدواير: البلوك جوه الدالة جوه الـ global. ولما تطلب متغير، المحرك بيدور من جوه لبره: النطاق الحالي ← اللي حواليه ← لحد الـ global — دي Scope Chain (سلسلة البحث).

③ الاتجاه ده باتجاه واحد صارم: الداخلي يشوف الخارجي، الخارجي عمره ما يشوف الداخلي. ولو الاسم مش موجود في السلسلة كلها ← ReferenceError.

٢ — شوفها بعينك: محاكي سلسلة البحث

المحاكي هنا شكله مختلف عن محاكي الـ Call Stack — صناديق جوه صناديق (ده شكل الـ scopes الحقيقي). راقب لحظة الـ lookup: هتشوف المحرك بيمشي في السلسلة صندوق-صندوق (الوهج الأصفر) لحد ما يلاقي الاسم (الأخضر). توقع قبل كل خطوة!

const app = "منصتي";
function show() {
  const user = "عمر";
  if (true) {
    let msg = "أهلاً";
    console.log(msg, user, app);
  }
}
show();
دوس «خطوة» عشان نبدأ.
Console:
الـ Scopes (صناديق متداخلة)

٣ — المقارنة: مين بيحترم البلوك ومين بيتجاهله؟

المتغير اتعرف بـ...جوه { } بلوك (if/for)جوه function
let / constمحبوس جوه البلوك ✓محبوس جوه الدالة ✓
var💥 بيتسرب بره البلوك!محبوس جوه الدالة ✓

var بتفهم الـ function scope بس — البلوكات بالنسبالها مش موجودة أصلاً (لأنها من زمن ماكانش فيه block scope في اللغة). ده مصدر باجات صامتة كلاسيكي، وسبب إضافي إن var مالهاش مكان في كود جديد.

✓ كل صف في الجدول متحقق منه بتشغيل Node.js حقيقي (2026-08-04).

الـ Shadowing (التظليل): لو عرّفت متغير جوه بنفس اسم متغير بره، الداخلي بيغطي على الخارجي جوه نطاقه — والخارجي بيفضل زي ما هو. ليه؟ فكّر بسلسلة البحث: المحرك بيلاقي الاسم في النطاق الداخلي الأول فبيقف — عمره ما بيوصل للخارجي. مش سحر، مجرد ترتيب البحث.

٤ — توقع قبل ما تشوف (3 تمارين)

{ let x = 1; }
console.log(x);
if (true) { var y = 1; }
console.log(y);
let n = "بره";
{
  let n = "جوه";
  console.log(n);
}
console.log(n);

٥ — اختبر نفسك

س1: متغير let اتعرف جوه if { } — تقدر توصله بعد قفلة البلوك؟

س2: ونفس السؤال لمتغير var اتعرف جوه if { }؟

س3: سلسلة البحث (Scope Chain) بتمشي في أنهي اتجاه؟

س4 (سؤال judgment): ليه حصر المتغير في أضيق نطاق ممكن بيعتبر كود أحسن؟

٦ — التحدي الأخير: اشرحها بصوت عالي

من غير ما تشغّل الكود ولا تبص على حاجة — اشرح إيه اللي هيتطبع وليه، وإيه حالة البرنامج بعد آخر سطر (فاكر ملاحظتي على نمطك؟ 😉):

const lang = "AR";
function render() {
  const lang = "EN";
  console.log(lang);
}
render();
console.log(lang);

الإجابة الكاملة تمر على: الـ shadowing (مين غطى على مين وفين) → سلسلة البحث في كل console.log → الناتج النهائي للسطرين → وإن البرنامج كمل عادي من غير أخطاء.

٧ — المصدر الأساسي للتعمق