مقدمه
با قابلیت Proxy میتوانید انواع الگوهای برنامهنویسی پیشرفته را به سادگی پیادهسازی کنید؛ مثل
اعتبارسنجی داده، محافظت از داده، ثبت رویداد (log)، ایجاد ویژگیهای داینامیک یا حتی شبیهسازی
مفاهیم ORM و reactivity.
استفاده از این الگوها باعث میشود کد ما تمیزتر، ماژولارتر و قابل تستتر باشد و کنترل کاملی روی
اشیا و رفتارها به ما میدهد.
الگوی لاگگیری (Logging)
میتوانید با Proxy تمامی عملیات روی شیء را لاگ کنید تا در توسعه و اشکالزدایی، از رفتار برنامه
مطلع شوید. در مثال زیر هر بار مقدار یک پراپرتی خوانده یا نوشته شود، پیام ثبت میشود.
JAVASCRIPT
let data = { count: 1 };
let logger = new Proxy(data, {
get(target, prop) {
console.log(`Read ${prop}`);
return target[prop];
},
set(target, prop, value) {
console.log(`Write ${prop}=${value}`);
target[prop] = value;
return true;
}
});
logger.count;
logger.count = 5;
در اینجا میتوانید با افزودن شرطهای بیشتر، فقط عملیات خاصی را لاگ کنید یا اطلاعات بیشتری (مانند
زمان یا کاربر) ثبت کنید. همچنین میتوانید لاگها را به سرور ارسال کنید یا در فایل ذخیره کنید
تا برای تحلیل رفتار برنامه استفاده شوند.
الگوی اعتبارسنجی (Validation)
با Proxy میتوانید فقط مقادیر مجاز را بپذیرید و بقیه را رد یا خطا ایجاد کنید. این کار بسیار برای
فرمها و دادههای حساس کاربردی است. در مثال زیر، اعتبارسنجی به گونهای انجام شده
که فقط مقادیر مثبت پذیرفته شوند.
JAVASCRIPT
let pos = {};
let valid = new Proxy(pos, {
set(target, prop, value) {
if (value < 0) {
throw new RangeError("invalid value");
}
target[prop] = value;
return true;
}
});
valid.x = 10;
valid.x = -5;
در اینجا
میتوانید انواع شرطهای اعتبارسنجی را اضافه کنید؛ مثلاً نوع داده، بازه مجاز، یا حتی اعتبارسنجی
async (مثلاً بررسی وجود نام کاربری در سرور). همچنین میتوانید پیام خطا را سفارشی کنید یا عملیات
خاصی هنگام خطا انجام دهید. این الگو برای جلوگیری از ورود دادههای نامعتبر به برنامه بسیار
کاربردی است.
الگوی محافظت از داده (Protection)
گاهی اوقات میخواهیم برخی دادهها فقط توسط بخش خاصی از برنامه قابل مشاهده یا تغییر باشند. با
استفاده از Proxy میتوانیم دسترسی به پراپرتیهایی که با یک پیشوند خاص (مثلاً _ ) شروع میشوند را
محدود کنیم تا از افشای اطلاعات حساس جلوگیری شود. این کار برای پیادهسازی encapsulation یا
جلوگیری از دسترسی مستقیم به دادههای داخلی بسیار مفید است. مثال زیر را ببینید.
JAVASCRIPT
let secret = { _hidden: "hidden", visible: "visible" };
let protector = new Proxy(secret, {
get(target, prop) {
if (prop.toString().startsWith("_"))
return undefined;
return target[prop];
}
});
console.log(protector.visible);
console.log(protector._hidden);
در اینجا
میتوانید علاوه بر get، متد set را هم پیادهسازی کنید تا حتی نوشتن روی پراپرتیهای حساس را نیز
محدود کنید. مثلاً اگر کسی بخواهد مقدار پراپرتیهایی که با _ شروع میشوند را تغییر دهد، خطا
دریافت کند یا عملیات نادیده گرفته شود. این روش برای پیادهسازی امنیت و جلوگیری از تغییرات
ناخواسته روی دادههای داخلی بسیار مفید است.
الگوهای پیشرفته (Dynamic/Reactive/Virtual)
پراکسیها برای ساخت ساختارهای دینامیک (پراپرتی داینامیک)، ساخت سیستمهای reactive (مثل Vue.js)
یا حتی شبیهسازی دیتابیسهای مجازی هم به کار میروند. هر جایی که بخواهید رفتار اشیا را در زمان
اجرا تغییر دهید، پراکسی راهحل ایدهآل است.
در مثال زیر اگر پراپرتیای وجود نداشت، به شکل خودکار مقدار پیشفرض تولید میشود.
JAVASCRIPT
let def = {};
let dynamic = new Proxy(def, {
get(target, prop) {
if (!(prop in target)) {
target[prop] = prop + "_value";
}
return target[prop];
}
});
console.log(dynamic.foo);
console.log(dynamic.bar);
در اینجا
میتوانید پراکسی را طوری گسترش دهید که مثلاً مقدار پیشفرض بر اساس نوع پراپرتی، یا حتی با
فراخوانی یک تابع async از سرور دریافت شود. همچنین میتوانید برای پیادهسازی کش (cache)، lazy
loading یا حتی ساختارهای ORM از این الگو استفاده کنید. این روش پایه بسیاری از فریمورکهای
reactive مدرن است و به شما اجازه میدهد رفتار اشیا را به صورت کاملاً داینامیک و قابل کنترل تغییر
دهید.