Scope وClosures في JavaScript بدون غموض
افهم كيف تبحث JavaScript عن المتغيرات، وكيف تتذكر الدالة البيئة التي أنشئت فيها، ومتى يفيد ذلك أو يتحول إلى تسريب للذاكرة.
كيف تبحث JavaScript عن متغير؟
عندما تقرأ اسم متغير، تبدأ JavaScript من النطاق الحالي. إذا لم تجده تنتقل إلى النطاق الخارجي الذي يحتوي الشيفرة، وتكرر ذلك حتى تصل إلى النطاق العام. تسمى هذه العلاقة Scope Chain. مكان كتابة الدالة هو الذي يحدد السلسلة، وليس المكان الذي استدعيت منه الدالة.
استخدام let وconst ينشئ نطاقًا للكتلة داخل الأقواس، بينما var يرتبط عادةً بنطاق الدالة. لهذا يفضل let وconst في الشيفرة الحديثة؛ حدودهما أوضح ويقل احتمال قراءة قيمة من مكان لم تقصده.
Closure كذاكرة مرتبطة بالدالة
عندما تعيد دالة داخلية من دالة خارجية، لا تختفي المتغيرات الخارجية التي تحتاجها الدالة الداخلية. تحتفظ الدالة بعلاقة مع بيئتها المعجمية، ويمكنها قراءة هذه القيم وتعديلها بعد انتهاء الاستدعاء الأصلي. هذا السلوك هو Closure.
ليست Closure نسخة جامدة من القيم، بل وصول إلى الروابط الموجودة في البيئة. إذا تغيرت القيمة التي يشير إليها الرابط، ترى الدالة القيمة الجديدة. فهم هذه النقطة يمنع التوقعات الخاطئة داخل الحلقات ومعالجات الأحداث.
function createCounter(start = 0) {
let value = start;
return {
increment() {
value += 1;
return value;
},
current() {
return value;
},
};
}
const tasks = createCounter(3);
tasks.increment(); // 4
tasks.current(); // 4استخدامات عملية سليمة
يمكن استخدام closures لإخفاء حالة لا يجب تعديلها مباشرة، كما في العدّاد السابق. وتفيد أيضًا في إنشاء دالة مهيأة بجزء من المدخلات: دالة تبني مدققًا لطول النص، أو معالج حدث يعرف معرّف العنصر دون البحث عنه كل مرة.
في React تظهر الفكرة داخل callbacks وeffects. كل عملية render تنشئ نطاقًا جديدًا، وقد يغلق callback على قيمة قديمة. لذلك يجب فهم تبعيات useEffect واستخدام التحديث الوظيفي للحالة عندما يعتمد التحديث على القيمة السابقة.
- •مصانع الدوال Function factories.
- •التهيئة الجزئية للمدخلات.
- •الاحتفاظ بحالة خاصة صغيرة مرتبطة بسلوك واضح.
متى تصبح Closure مشكلة؟
إذا احتفظ callback طويل العمر بمرجع إلى كائن ضخم لم يعد مطلوبًا، فلن يتمكن جامع القمامة من تحرير ذلك الكائن. المشكلة ليست في closures نفسها، بل في عمر المرجع وحجم البيئة التي أبقيتها متاحة. أزل event listeners عند انتهاء استخدامها، وألغ المؤقتات والاشتراكات، ولا تغلق على بيانات أكبر مما تحتاجه الدالة.
عند التصحيح، اسأل: أين أنشئت هذه الدالة؟ ما الأسماء الخارجية التي تقرؤها؟ هل تغيرت القيم منذ إنشائها؟ ثم استخدم DevTools لفحص listeners والذاكرة إذا كان العطل تراكميًا. هذا التحليل أبسط وأدق من وصف أي سلوك غريب بأنه مشكلة scope.
المراجع ومزيد من القراءة
عن المؤلف
يراجع أسامة زيدان محتوى كود هاب بهدف تقديم شرح عربي واضح يربط المفاهيم البرمجية بالقرارات التي يواجهها المتعلم أثناء التطبيق.
صفحة المؤلف