يتطلب مستوى محترف. ده مقال لمطورين JavaScript عندهم خبرة سنة على الأقل، فاهمين getters/setters والـ prototype chain، ومحتاجين يراقبوا تعديلات الـ state في تطبيق معقّد بدون لمس الكود الأصلي.
لو dashboard React عندك بيرجّع state غلط بعد 4 تعديلات متتالية ومحدّش عارف مين عدّل آخر مرة، انت محتاج Proxy. 12 سطر JavaScript بيخلّوك تمسك أي قراءة أو كتابة على object قبل ما تحصل، بدون لمس سطر من الكود الأصلي.
JavaScript Proxy للمحترف: راقب أي قراءة أو كتابة على object
المشكلة باختصار
في تطبيق React فيه 14 component بيقرأوا ويكتبوا على نفس Zustand store، أي bug في الـ state بيتسبب فيه واحد من الـ 14. الـ Redux DevTools بيشوف الـ actions اللي بتعدّي من dispatch بس، لكن لو الكود بيلمس object مباشرة بـ store.user = newValue، انت أعمى تماماً.
الحل الشائع: تضيف console.log يدوي في كل setter. التكلفة الحقيقية: 47 سطر زيادة موزّعين على 14 component، واحتمال نسيان موضع. الحل الأنظف: غلّف الـ object بـ Proxy واحد، وكل قراءة وكتابة بتعدّي عليه بدون لمس الكود الموجود.
مثال بسيط للمبتدئ: السكرتير الشخصي قبل الباب
تخيّل إنك مدير عام في شركة، ومكتبك فيه ملفات حساسة. أي حد عايز يقرا أو يعدّل في ملف لازم يدخل عن طريق سكرتيرك أولاً. السكرتير بيسجّل في دفتر: مين دخل، إمتى، إيه الملف اللي طلبه، عدّل ولا قرا بس، وفيه لما بيرفض الدخول لشخص معيّن.
أنت كمدير ما اتغيّرتش، الملفات في مكانها زي ما هي، لكن الدنيا بقت متتبّعة بالكامل. Proxy في JavaScript بيلعب دور السكرتير ده بالظبط: بيقف بين الـ caller والـ object، ويسجّل أو يعدّل أو يرفض أي عملية تمر عليه.
التعريف العلمي: ميكانيكية Proxy في الـ Spec
الـ Proxy عبارة عن exotic object متعرّف في ECMAScript 2024 Specification قسم 10.5 — Proxy Object Internal Methods and Internal Slots. لما تكتب new Proxy(target, handler)، الـ engine بيستبدل الـ default internal methods (زي [[Get]] و [[Set]] و [[Has]] و [[DeleteProperty]] و [[OwnPropertyKeys]]) بالـ traps اللي انت بتعرّفها في handler object.
يعني لما تكتب obj.x، الـ engine مش بيقرا مباشرة من الذاكرة — هو بيستدعي handler.get(target, "x", receiver) أولاً. ده مش syntactic sugar فوق getters/setters. ده interception على مستوى الـ MOP (Meta-Object Protocol)، ومش ممكن تعمله بـ Object.defineProperty على properties مش موجودة أصلاً وقت التعريف.