Scope وسلسلة البحث — مين يشوف مين؟
ليه الدرس ده؟ الـ Scope هو آخر قطعة في أساس الأسبوع الأول — ومن غيره الـ Closures (أهم موضوع في المرحلة كلها حسب roadmap بتاعك) هيبقى طلاسم. وهو كمان مصدر باجات يومية حقيقية في الشغل.
🔁 مراجعة سريعة قبل ما تبدأ (~5 دقايق):
- ورقة نموذج التنفيذ — ركز على جدول الـ hoisting (بتفتح في تاب جديد)
- اسأل نفسك من الذاكرة: إيه فرق var عن let في مرحلة الإنشاء؟ وليه TDZ تصميم كويس؟ — طلعت بسهولة؟ ادخل. لأ؟ بصة سريعة على محاكي 0002
١ — الفكرة في 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();
٣ — المقارنة: مين بيحترم البلوك ومين بيتجاهله؟
| المتغير اتعرف بـ... | جوه { } بلوك (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 → الناتج النهائي للسطرين → وإن البرنامج كمل عادي من غير أخطاء.
٧ — المصدر الأساسي للتعمق
- MDN — Scope — التعريف المرجعي للأنواع التلاتة.
- javascript.info — Variable scope, closure — اقرا أول 3 أقسام بس (Blocks / Nested functions / Lexical Environment خفيف) — وقف عند الـ closures: دي بتاعة الأسبوع 3 إن شاء الله، وهتبقى أحلى وأنت جاهز ليها.
- ورقة المراجعة: reference/js-execution-model.html (اتضاف فيها قسم الـ scope)