أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالمناهج والباقات
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
البرمجة بالعربي

Hoisting في JavaScript للمبتدئ: ليه المتغير بيطلّع undefined قبل ما تعرّفه

مبتدئ١٩ يونيو ٢٠٢٦5 دقائق قراءة
Hoisting في JavaScript للمبتدئ: ليه المتغير بيطلّع undefined قبل ما تعرّفه

المستوى: مبتدئ. الكلام ده موجّه للي لسه بادئ في JavaScript أو بيتعلّم برمجة من شهور قليلة. مش محتاج تكون عارف حاجة عن الـ memory أو الـ compiler عشان تفهمه.

Hoisting في JavaScript: ليه المتغير بيطلّع undefined قبل سطر تعريفه

لو طبعت متغير قبل السطر اللي عرّفته فيه ولقيت الناتج undefined بدل ما الكود يقع بخطأ، انت قابلت الـ Hoisting. المقال ده هيخليك تفهم ليه بيحصل ده بالظبط، وإزاي تكتب كودك بحيث ميفاجئكش تاني.

شاشة محرر كود تعرض سطور JavaScript فيها تعريف متغيرات بـ var و let لشرح مفهوم الـ Hoisting

المشكلة باختصار

شوف الكود ده. منطقيًا المفروض يقع، لأنك بتستخدم x قبل ما تعرّفها:

JavaScript
console.log(x); // إيه اللي هيطبع؟
var x = 5;
console.log(x); // وهنا؟

الناتج الفعلي على Node 22 بيطلع كده:

JavaScript
undefined
5

السطر الأول مرماهوش خطأ، وطبع undefined. ده اللي بيلخبط أي حد بادئ. كأن JavaScript عرفت إن في متغير اسمه x قبل ما توصل لسطر تعريفه. وده بالظبط اللي بيحصل.

افهمها الأول بمثال المخزن

تخيّل عامل في مخزن. قبل ما يبدأ شغل اليوم، بيقرأ ورقة الطلبات كلها مرة واحدة، وبيكتب على رف فاضي أسماء كل الصناديق اللي هيحتاجها النهارده. الرف دلوقتي فيه أسماء بس، من غير محتوى جوه الصناديق.

بعد كده بيبدأ ينفّذ الطلبات سطر سطر. أول ما يوصل لطلب "املأ صندوق x بـ 5 قطع"، ساعتها بس الصندوق بيتملي.

فلو حد سأل العامل عن صندوق x قبل ما يوصل لسطر التعبئة، هيلاقي الاسم موجود على الرف بس الصندوق فاضي. الاسم اتحجز بدري، القيمة لسه متحطتش. الكلمة "فاضي" دي هي undefined في JavaScript.

رافعة شوكية ترفع صناديق لأعلى المخزن كتشبيه لرفع تعريفات المتغيرات لأعلى النطاق في الـ Hoisting

التعريف العلمي للـ Hoisting

بالتفاصيل: قبل ما JavaScript تشغّل كودك سطر بسطر، بتعمل مرور أولي على الـ scope كله. في المرور ده، بتحجز مكان في الذاكرة لكل تعريفات var وكل function declarations، وبترفعها مفاهيميًا لأعلى الـ scope. ده اللي اسمه Hoisting (الرفع).

المهم اللي لازم يثبت في دماغك: اللي بيتـرفع هو التعريف بس، مش القيمة. يعني var x = 5 الكومبايلر بيفهمها كأنها سطرين منفصلين:

JavaScript
var x;        // ده بيترفع لأعلى الـ scope (الاسم اتحجز)
// ... باقي الكود ...
x = 5;        // ده بيفضل مكانه (القيمة بتتحط هنا فقط)

عشان كده console.log(x) قبل سطر x = 5 بيطبع undefined مش بيقع بخطأ: الاسم موجود، القيمة لسه لأ. التعريف الرسمي ده مأخوذ من توثيق Mozilla MDN عن الـ Hoisting.

الفرق المهم: var مقابل let و const

هنا اللي لازم تركّز فيه. let و const بيتـرفعوا برضه، بس بطريقة مختلفة بتحميك. جرّب الكود ده:

JavaScript
console.log(y); // ❌ هنا بيقع
let y = 5;

الناتج مش undefined المرة دي، ده خطأ صريح:

JavaScript
ReferenceError: Cannot access 'y' before initialization

الفرق إن let و const بيتحجزلهم مكان من بداية الـ scope، بس JavaScript بتمنعك تستخدمهم لحد سطر التعريف الفعلي. المنطقة دي بين بداية الـ scope وسطر التعريف اسمها Temporal Dead Zone أو منطقة الموت الزمني. أي محاولة تقرأ المتغير فيها بترمي ReferenceError.

ده مش عيب، ده ميزة. let و const بيحوّلوا غلطة صامتة (undefined بيمشي ويلخبطك بعدين) لغلطة صريحة بتوقفك في مكانها. الفرق ده موثّق في مواصفة ECMAScript الرسمية تحت مفهوم الـ TDZ.

سيناريو واقعي: ليه ده بيوجعك فعلًا

تخيّل عندك دالة بتحسب الخصم على طلب في موقع e-commerce بـ 50 ألف زيارة في اليوم:

JavaScript
function calcTotal(price) {
  if (price > 100) {
    var discount = price * 0.1;
  }
  return price - discount; // discount ممكن تكون undefined
}

console.log(calcTotal(50)); // النتيجة: NaN مش 50

المشكلة: var discount اتـرفعت لأول الدالة، فهي موجودة برة الـ if كمان. لما price أقل من 100، الشرط ما بيتنفذش، فـ discount بتفضل undefined. وبعدين 50 - undefined بيطلع NaN. ده bug صامت ممكن يفضل في الـ production أسابيع. لو كنت كتبتها let discount جوه الـ if، الكود كان وقع وقت التطوير وعرّفك بالغلط بدري.

trade-offs: تكسب إيه وتخسر إيه

  • استخدام let و const: بتكسب أمان وأخطاء صريحة بدري. بتخسر... تقريبًا لا شيء. ده السبب إن الكود الحديث بطّل يستخدم var.
  • الاعتماد على hoisting الدوال: function declarations بتترفع بالكامل (الاسم والجسم)، فتقدر تناديها قبل تعريفها. ده بيخليك ترتب الكود بحرية، بس بيخفي ترتيب الاعتماديات على القارئ الجديد.
  • الافتراض هنا: الكلام ده على JavaScript حديث (ES6 وما بعده) على Node 18 أو أحدث. الكود القديم اللي مليان var له سلوك أصعب في التتبع.

متى متشغلش بالك بالموضوع

لو بتكتب كودك كله بـ const وبتنزل لـ let بس وقت الحاجة، وبتعرّف المتغير قبل ما تستخدمه دايمًا (وده الطبيعي)، فالـ Hoisting مش هيقابلك كمشكلة أبدًا. الموضوع ده بيهمك في حالتين: لما تقرأ كود قديم فيه var، أو لما تتسأل عنه في interview. غير كده، القاعدة البسيطة بتكفيك.

الخطوة التالية

افتح أي ملف JavaScript عندك ودوّر على كلمة var. غيّرها لـ const، ولو الكود اشتكى إنه بيعيد إسناد القيمة، غيّرها لـ let. شغّل الكود تاني. لو كل حاجة اشتغلت زي ما هي، يبقى انت دلوقتي محمي من 90% من مفاجآت الـ Hoisting. والباقي بقى مجرد معرفة بتفهم بيها كود غيرك.

المصادر

  • توثيق Mozilla MDN عن الـ Hoisting: developer.mozilla.org/en-US/docs/Glossary/Hoisting
  • توثيق MDN عن let والـ Temporal Dead Zone: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
  • مواصفة ECMAScript الرسمية (قسم Declarations and the Variable Environment): tc39.es/ecma262
  • توثيق Node.js عن إصدارات V8 المدعومة: nodejs.org/en/docs

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة