Obyekt xulq-atvorini o'zgartirish uchun JavaScript Proksi patternlarini o'rganing. Validatsiya, virtualizatsiya, kuzatuv va boshqa ilg'or usullarni kod misollari bilan o'rganing.
JavaScript Proksi Patternlari: Obyekt Xulq-atvorini O'zgartirishni O'zlashtirish
JavaScript Proksi obyekti obyektlardagi fundamental operatsiyalarni to'xtatib turish va moslashtirish uchun kuchli mexanizmni taqdim etadi. Bu imkoniyat obyekt xulq-atvorini boshqarish uchun keng ko'lamli dizayn patternlari va ilg'or usullarga yo'l ochadi. Ushbu keng qamrovli qo'llanma turli xil Proksi patternlarini o'rganadi va ularning amaliy kod misollari bilan qo'llanilishini ko'rsatadi.
JavaScript Proksi nima?
Proksi obyekti boshqa bir obyektni (maqsad) o'rab oladi va uning operatsiyalarini to'xtatib turadi. Ushbu operatsiyalar, "traplar" deb nomlanadi va xususiyatlarni qidirish, tayinlash, sanash va funksiyalarni chaqirishni o'z ichiga oladi. Proksi sizga ushbu operatsiyalardan oldin, keyin yoki ularning o'rniga bajariladigan maxsus mantiqni belgilashga imkon beradi. Proksining asosiy tushunchasi JavaScript tilining o'zi xulq-atvorini manipulyatsiya qilish imkonini beruvchi "metaprogrammalashtirish" ni o'z ichiga oladi.
Proksi yaratishning asosiy sintaksisi:
const proxy = new Proxy(target, handler);
- target: Siz proksi qilmoqchi bo'lgan asl obyekt.
- handler: Proksining maqsad ustidagi operatsiyalarni qanday to'xtatib turishini belgilaydigan usullarni (traplarni) o'z ichiga olgan obyekt.
Umumiy Proksi Traplari
Handler obyekti bir nechta traplarni belgilashi mumkin. Quyida eng ko'p ishlatiladiganlaridan ba'zilari keltirilgan:
- get(target, property, receiver): Xususiyatga kirishni to'xtatadi (masalan,
obj.property
). - set(target, property, value, receiver): Xususiyatga qiymat berishni to'xtatadi (masalan,
obj.property = value
). - has(target, property):
in
operatorini to'xtatadi (masalan,'property' in obj
). - deleteProperty(target, property):
delete
operatorini to'xtatadi (masalan,delete obj.property
). - apply(target, thisArg, argumentsList): Funksiya chaqiruvlarini to'xtatadi (maqsad funksiya bo'lganda).
- construct(target, argumentsList, newTarget):
new
operatorini to'xtatadi (maqsad konstruktor funksiyasi bo'lganda). - getPrototypeOf(target):
Object.getPrototypeOf()
chaqiruvlarini to'xtatadi. - setPrototypeOf(target, prototype):
Object.setPrototypeOf()
chaqiruvlarini to'xtatadi. - isExtensible(target):
Object.isExtensible()
chaqiruvlarini to'xtatadi. - preventExtensions(target):
Object.preventExtensions()
chaqiruvlarini to'xtatadi. - getOwnPropertyDescriptor(target, property):
Object.getOwnPropertyDescriptor()
chaqiruvlarini to'xtatadi. - defineProperty(target, property, descriptor):
Object.defineProperty()
chaqiruvlarini to'xtatadi. - ownKeys(target):
Object.getOwnPropertyNames()
vaObject.getOwnPropertySymbols()
chaqiruvlarini to'xtatadi.
Proksi Patternlari va Foydalanish Holatlari
Keling, ba'zi umumiy Proksi patternlarini va ularni real hayotiy stsenariylarda qanday qo'llash mumkinligini ko'rib chiqamiz:
1. Validatsiya
Validatsiya patterni xususiyatlarga qiymat berishda cheklovlarni amalga oshirish uchun Proksidan foydalanadi. Bu ma'lumotlar yaxlitligini ta'minlash uchun foydalidir.
const validator = {
set: function(obj, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('Yosh butun son emas');
}
if (value < 0) {
throw new RangeError('Yosh manfiy bo\'lmagan butun son bo\'lishi kerak');
}
}
// Qiymatni saqlash uchun standart xatti-harakat
obj[prop] = value;
// Muvaffaqiyatni bildirish
return true;
}
};
let person = {};
let proxy = new Proxy(person, validator);
proxy.age = 25; // Yaroqli
console.log(proxy.age); // Chiqish: 25
try {
proxy.age = 'young'; // TypeError xatosini chiqaradi
} catch (e) {
console.log(e); // Chiqish: TypeError: Yosh butun son emas
}
try {
proxy.age = -10; // RangeError xatosini chiqaradi
} catch (e) {
console.log(e); // Chiqish: RangeError: Yosh manfiy bo'lmagan butun son bo'lishi kerak
}
Misol: Foydalanuvchi ma'lumotlarini validatsiya qilish zarur bo'lgan elektron tijorat platformasini ko'rib chiqing. Proksi yosh, elektron pochta formati, parol kuchi va boshqa maydonlar uchun qoidalarni amalga oshirishi va noto'g'ri ma'lumotlarning saqlanishini oldini olishi mumkin.
2. Virtualizatsiya (Kechiktirilgan Yuklash)
Virtualizatsiya, shuningdek, kechiktirilgan yuklash (lazy loading) deb ham ataladi, qimmat resurslarni ular haqiqatdan ham kerak bo'lguncha yuklashni kechiktiradi. Proksi haqiqiy obyekt uchun joy egallovchi vazifasini bajarishi mumkin, uni faqat biron bir xususiyatga murojaat qilinganda yuklaydi.
const expensiveData = {
load: function() {
console.log('Qimmatli ma\'lumotlar yuklanmoqda...');
// Ko'p vaqt talab qiladigan operatsiyani simulyatsiya qilish (masalan, ma'lumotlar bazasidan olish)
return new Promise(resolve => {
setTimeout(() => {
resolve({
data: 'Bu qimmatli ma\'lumot'
});
}, 2000);
});
}
};
const lazyLoadHandler = {
get: function(target, prop) {
if (prop === 'data') {
console.log('Ma\'lumotlarga kirilmoqda, agar kerak bo\'lsa yuklanmoqda...');
return target.load().then(result => {
target.data = result.data; // Yuklangan ma'lumotlarni saqlash
return result.data;
});
} else {
return target[prop];
}
}
};
const lazyData = new Proxy(expensiveData, lazyLoadHandler);
console.log('Dastlabki kirish...');
lazyData.data.then(data => {
console.log('Ma\'lumot:', data); // Chiqish: Ma'lumot: Bu qimmatli ma'lumot
});
console.log('Keyingi kirish...');
lazyData.data.then(data => {
console.log('Ma\'lumot:', data); // Chiqish: Ma'lumot: Bu qimmatli ma'lumot (keshdan yuklandi)
});
Misol: Ko'p sonli tafsilotlar va tegishli medialarni o'z ichiga olgan foydalanuvchi profillariga ega yirik ijtimoiy media platformasini tasavvur qiling. Barcha profil ma'lumotlarini darhol yuklash samarasiz bo'lishi mumkin. Proksi bilan virtualizatsiya avval asosiy profil ma'lumotlarini yuklashga, so'ngra foydalanuvchi ushbu bo'limlarga o'tgandagina qo'shimcha ma'lumotlar yoki media kontentini yuklashga imkon beradi.
3. Jurnalga Yozish va Kuzatish
Proksilar xususiyatlarga kirish va o'zgartirishlarni kuzatish uchun ishlatilishi mumkin. Bu disk raskadrovka, audit va ishlash monitoringi uchun qimmatlidir.
const logHandler = {
get: function(target, prop, receiver) {
console.log(`GET ${prop}`);
return Reflect.get(target, prop, receiver);
},
set: function(target, prop, value) {
console.log(`SET ${prop} ga ${value}`);
target[prop] = value;
return true;
}
};
let obj = { name: 'Alice' };
let proxy = new Proxy(obj, logHandler);
console.log(proxy.name); // Chiqish: GET name, Alice
proxy.age = 30; // Chiqish: SET age ga 30
Misol: Hamkorlikda hujjat tahrirlash dasturida Proksi hujjat tarkibiga kiritilgan har bir o'zgarishni kuzatishi mumkin. Bu audit izini yaratish, bekor qilish/qaytarish funksionalligini yoqish va foydalanuvchi hissalari haqida ma'lumot berish imkonini beradi.
4. Faqat O'qish Uchun Ko'rinishlar
Proksilar obyektlarning faqat o'qish uchun mo'ljallangan ko'rinishlarini yaratishi mumkin, bu esa tasodifiy o'zgartirishlarning oldini oladi. Bu maxfiy ma'lumotlarni himoya qilish uchun foydalidir.
const readOnlyHandler = {
set: function(target, prop, value) {
console.error(`${prop} xususiyatini o'rnatib bo'lmaydi: obyekt faqat o'qish uchun`);
return false; // Belgilash operatsiyasi muvaffaqiyatsiz bo'lganini bildirish
},
deleteProperty: function(target, prop) {
console.error(`${prop} xususiyatini o'chirib bo'lmaydi: obyekt faqat o'qish uchun`);
return false; // O'chirish operatsiyasi muvaffaqiyatsiz bo'lganini bildirish
}
};
let data = { name: 'Bob', age: 40 };
let readOnlyData = new Proxy(data, readOnlyHandler);
try {
readOnlyData.age = 41; // Xatolik chiqaradi
} catch (e) {
console.log(e); // Xato chiqmaydi, chunki 'set' trapi false qaytaradi.
}
try {
delete readOnlyData.name; // Xatolik chiqaradi
} catch (e) {
console.log(e); // Xato chiqmaydi, chunki 'deleteProperty' trapi false qaytaradi.
}
console.log(data.age); // Chiqish: 40 (o'zgarishsiz)
Misol: Ba'zi foydalanuvchilar hisob ma'lumotlariga faqat o'qish uchun ruxsatga ega bo'lgan moliyaviy tizimni ko'rib chiqing. Proksi bu foydalanuvchilarning hisob balanslarini yoki boshqa muhim ma'lumotlarni o'zgartirishini oldini olish uchun ishlatilishi mumkin.
5. Standart Qiymatlar
Proksi mavjud bo'lmagan xususiyatlar uchun standart qiymatlarni taqdim etishi mumkin. Bu kodni soddalashtiradi va null/undefined tekshiruvlarini oldini oladi.
const defaultValuesHandler = {
get: function(target, prop, receiver) {
if (!(prop in target)) {
console.log(`${prop} xususiyati topilmadi, standart qiymat qaytarilmoqda.`);
return 'Standart Qiymat'; // Yoki boshqa mos keladigan standart qiymat
}
return Reflect.get(target, prop, receiver);
}
};
let config = { apiUrl: 'https://api.example.com' };
let configWithDefaults = new Proxy(config, defaultValuesHandler);
console.log(configWithDefaults.apiUrl); // Chiqish: https://api.example.com
console.log(configWithDefaults.timeout); // Chiqish: timeout xususiyati topilmadi, standart qiymat qaytarilmoqda. Standart Qiymat
Misol: Konfiguratsiyani boshqarish tizimida Proksi mavjud bo'lmagan sozlamalar uchun standart qiymatlarni taqdim etishi mumkin. Masalan, agar konfiguratsiya faylida ma'lumotlar bazasiga ulanish vaqti ko'rsatilmagan bo'lsa, Proksi oldindan belgilangan standart qiymatni qaytarishi mumkin.
6. Metama'lumotlar va Annotatsiyalar
Proksilar asl obyektni o'zgartirmasdan qo'shimcha ma'lumot berib, obyektlarga metama'lumotlar yoki annotatsiyalarni biriktirishi mumkin.
const metadataHandler = {
get: function(target, prop, receiver) {
if (prop === '__metadata__') {
return { description: 'Bu obyekt uchun metama\'lumot' };
}
return Reflect.get(target, prop, receiver);
}
};
let article = { title: 'Proksilarga kirish', content: '...' };
let articleWithMetadata = new Proxy(article, metadataHandler);
console.log(articleWithMetadata.title); // Chiqish: Proksilarga kirish
console.log(articleWithMetadata.__metadata__.description); // Chiqish: Bu obyekt uchun metama'lumot
Misol: Kontentni boshqarish tizimida Proksi maqolalarga muallif ma'lumotlari, nashr etilgan sana va kalit so'zlar kabi metama'lumotlarni biriktirishi mumkin. Ushbu metama'lumotlar kontentni qidirish, filtrlash va kategoriyalarga ajratish uchun ishlatilishi mumkin.
7. Funksiyani Tutib Olish
Proksilar funksiya chaqiruvlarini to'xtatib, jurnalga yozish, validatsiya yoki boshqa oldindan yoki keyingi ishlov berish mantiqini qo'shish imkonini beradi.
const functionInterceptor = {
apply: function(target, thisArg, argumentsList) {
console.log('Funksiya argumentlar bilan chaqirilmoqda:', argumentsList);
const result = target.apply(thisArg, argumentsList);
console.log('Funksiya qaytardi:', result);
return result;
}
};
function add(a, b) {
return a + b;
}
let proxiedAdd = new Proxy(add, functionInterceptor);
let sum = proxiedAdd(5, 3); // Chiqish: Funksiya argumentlar bilan chaqirilmoqda: [5, 3], Funksiya qaytardi: 8
console.log(sum); // Chiqish: 8
Misol: Bank dasturida Proksi tranzaksiya funksiyalariga chaqiruvlarni to'xtatib, har bir tranzaksiyani jurnalga yozib olishi va tranzaksiyani bajarishdan oldin firibgarlikni aniqlash tekshiruvlarini amalga oshirishi mumkin.
8. Konstruktorni Tutib Olish
Proksilar konstruktor chaqiruvlarini to'xtatib, obyekt yaratishni moslashtirish imkonini beradi.
const constructorInterceptor = {
construct: function(target, argumentsList, newTarget) {
console.log(target.name, 'ning yangi nusxasi yaratilmoqda, argumentlar:', argumentsList);
const obj = new target(...argumentsList);
console.log('Yangi nusxa yaratildi:', obj);
return obj;
}
};
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
let ProxiedPerson = new Proxy(Person, constructorInterceptor);
let person = new ProxiedPerson('Alice', 28); // Chiqish: Person ning yangi nusxasi yaratilmoqda, argumentlar: ['Alice', 28], Yangi nusxa yaratildi: Person { name: 'Alice', age: 28 }
console.log(person);
Misol: O'yin ishlab chiqish freymvorkida Proksi o'yin obyektlarini yaratishni to'xtatib, avtomatik ravishda noyob ID'larni tayinlashi, standart komponentlarni qo'shishi va ularni o'yin dvigatelida ro'yxatdan o'tkazishi mumkin.
Ilg'or Mulohazalar
- Ishlash samaradorligi: Proksilar moslashuvchanlikni taqdim etsa-da, ular ishlash samaradorligiga salbiy ta'sir ko'rsatishi mumkin. Ayniqsa, yuqori samaradorlik talab qilinadigan ilovalarda Proksilardan foydalanishning afzalliklari ishlash xarajatlaridan ustun ekanligiga ishonch hosil qilish uchun kodingizni sinab ko'rish va profilini yaratish muhimdir.
- Moslik: Proksilar JavaScript-ga nisbatan yaqinda qo'shilgan, shuning uchun eski brauzerlar ularni qo'llab-quvvatlamasligi mumkin. Eski muhitlar bilan moslikni ta'minlash uchun xususiyatlarni aniqlash yoki polifillardan foydalaning.
- Qaytariladigan Proksilar:
Proxy.revocable()
usuli bekor qilinishi mumkin bo'lgan Proksi yaratadi. Proksini bekor qilish keyingi operatsiyalarning to'xtatilishini oldini oladi. Bu xavfsizlik yoki resurslarni boshqarish maqsadlarida foydali bo'lishi mumkin. - Reflect API: Reflect API Proksi traplarining standart xatti-harakatlarini bajarish uchun usullarni taqdim etadi.
Reflect
-dan foydalanish Proksi kodingizning til spetsifikatsiyasiga mos kelishini ta'minlaydi.
Xulosa
JavaScript Proksilari obyekt xulq-atvorini moslashtirish uchun kuchli va ko'p qirrali mexanizmni taqdim etadi. Turli xil Proksi patternlarini o'zlashtirib, siz yanada mustahkam, qo'llab-quvvatlanadigan va samarali kod yozishingiz mumkin. Validatsiya, virtualizatsiya, kuzatuv yoki boshqa ilg'or usullarni amalga oshirasizmi, Proksilar obyektlarga qanday kirish va manipulyatsiya qilinishini boshqarish uchun moslashuvchan yechimni taklif etadi. Har doim ishlash samaradorligiga ta'sirini hisobga oling va maqsadli muhitlaringiz bilan mosligini ta'minlang. Proksilar zamonaviy JavaScript dasturchisining arsenalidagi asosiy vosita bo'lib, kuchli metaprogrammalashtirish usullarini yoqib beradi.
Qo'shimcha O'rganish
- Mozilla Developer Network (MDN): JavaScript Proksi
- Exploring JavaScript Proxies: Smashing Magazine Maqolasi