Proxy در جاوا اسکریپت


JavaScript Proxy یک object است که یک object دیگر را wrap می کند و عملیات های اساسی object هدف را intercepts می کند.
عملیات های اساسی می تواند جستجوی property ، تخصیص(assignment)، شمارش، فراخوانی تابع و غیره باشد.
ایجاد یکproxy object
برای ایجاد یک proxy object جدید،شما باید از syntax زیر استفاده کنید:
1 |
let proxy = new Proxy(target, handler); |
در این syntax :
- target – همان object هدف که wrap شده است.
- handler – یک object است که شامل متدهایی برای کنترل رفتارهای target است. متدهای داخل handler، در واقع traps نامیده می شوند.
یک مثال ساده از proxy
ابتدا یک object به نام user تعریف کنید:
1 2 3 4 5 |
const user = { firstName: 'John', lastName: 'Doe', email: 'john.doe@example.com', } |
سپس یک handler object تعریف کنید:
1 2 3 4 5 6 |
const handler = { get(target, property) { console.log(`Property ${property} has been read.`); return target[property]; } } |
در سومین گام،یک proxy
ایجاد کنید:
1 |
const proxyUser = new Proxy(user, handler); |
proxyUser از user object برای ذخیره داده ها استفاده می کند. ProxyUser می تواند به تمام properties های user دسترسی داشته باشد.
سپس، از طریق proxyUser
به properties های firstName
و lastName
شی user
دسترسی پیدا کنید:
1 2 |
console.log(proxyUser.firstName); console.log(proxyUser.lastName); |
خروجی :
1 2 3 4 |
Property firstName has been read. John Property lastName has been read. Doe |
زمانی که از طریق proxyUser به یک property از user object دسترسی پیدا می کنید،متد ()get در handler object فراخوانی می شود.
اگر شما user object را تغییر دهید،این تغییرات در proxyUser نیز منعکس و اعمال می شود:
1 2 |
user.firstName = 'Jane'; console.log(proxyUser.firstName); |
خروجی:
1 2 |
Property firstName has been read. Jane |
به طور مشابه، تغییر در proxyUser در object اصلی (user) منعکس خواهد شد:
1 2 |
proxyUser.lastName = 'William'; console.log(user.lastName); |
خروجی:
1 |
William |
Proxy Traps
get()
trap
هنگامی که یک property از target
object از طریق proxy objectقابل دسترسی باشد، ()get فراخوانی می شود.
در مثال قبلی، زمانی که یک property از user object توسط proxyUser object دسترسی پیدا می کند، پیامی چاپ می شود.
به طور کلی، شما می توانید یک منطق(logic) سفارشی را در get()
trap هنگام دسترسی به یک property توسعه دهید.
به عنوان مثال، می توانید از get()
trap برای تعریف computed properties برای target object استفاده کنید. computed properties ،در واقع properties هایی هستند که مقادیر آنها بر اساس مقادیر properties های موجود محاسبه می شود.
user object دارای یک property به نام fullName نیست، می توانید ازget() trap برای ایجاد fullName بر اساس propertiesهای firstName و lastName استفاده کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
const user = { firstName: 'John', lastName: 'Doe' } const handler = { get(target, property) { return property === 'fullName' ? `${target.firstName} ${target.lastName}` : target[property]; } }; const proxyUser = new Proxy(user, handler); console.log(proxyUser.fullName); |
خروجی :
1 |
John Doe |
set()
trap
set() trap رفتار و عملیات مربوط به ایجاد و تعریف یک property برای target
object را کنترل می کند.
فرض کنید سن کاربر باید بیشتر از 18 سال باشد. برای اعمال این محدودیت، یکset() trap به صورت زیر باید ایجاد کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
const user = { firstName: 'John', lastName: 'Doe', age: 20 } const handler = { set(target, property, value) { if (property === 'age') { if (typeof value !== 'number') { throw new Error('Age must be a number.'); } if (value < 18) { throw new Error('The user must be 18 or older.') } } target[property] = value; } }; const proxyUser = new Proxy(user, handler); |
ابتدا سن کاربر رو به جای عدد یک string در نظر بگیرید:
1 |
proxyUser.age = 'foo'; |
خروجی:
1 |
Error: Age must be a number. |
سپس، سن کاربر را 16 در نظر بگیرید:
1 |
proxyUser.age = '16'; |
خروجی:
1 |
The user must be 18 or older. |
در سومین مرحله، سن کاربر را 21 در نظر بگیرید:
1 |
proxyUser.age = 21; |
هیچ خطایی رخ نمی دهد.
apply()
trap
متد ()handler.apply یک trap برای فراخوانی تابع است.syntax آن مشابه زیر است:
1 2 3 4 5 |
let proxy = new Proxy(target, { apply: function(target, thisArg, args) { //... } }); |
به مثال زیر توجه کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
const user = { firstName: 'John', lastName: 'Doe' } const getFullName = function (user) { return `${user.firstName} ${user.lastName}`; } const getFullNameProxy = new Proxy(getFullName, { apply(target, thisArg, args) { return target(...args).toUpperCase(); } }); console.log(getFullNameProxy(user)); // |
خروجی:
1 |
JOHN DOE |
دیگر trap ها
موارد زیر trap های بیشتری هستند که می توانید بنا بر نیاز از آن ها استفاده کنید:
construct
getPrototypeOf
setPrototypeOf
isExtensible
preventExtensions
getOwnPropertyDescriptor
دیدگاهتان را بنویسید