JavaScript'de Proxy Özelliği: Ne İşe Yarar ve Nasıl Kullanılır?
Günümüzde JavaScript, web geliştiricilerin vazgeçilmez dillerinden biri haline gelmiştir. JavaScript'in bu denli popüler olmasında, sürekli geliştirilen ve yeni özellikler eklenen dil yapısı büyük rol oynar. Proxy, JavaScript'in ES6 ile eklenen güçlü ve esnek özelliklerinden biridir. Bu makalede, JavaScript'de Proxy özelliğinin ne olduğunu, nasıl kullanılacağını ve özellikle hangi amaçlarla kullanıldığını inceleyeceğiz. Ayrıca, JavaScript frameworklerindeki reactive konsepti ile Proxy özelliğini nasıl bağlayabileceğimize dair örnekler de sunacağız.
Proxy Nedir?
JavaScript'de Proxy, bir nesnenin üzerinde yapılan işlemleri özelleştiren ve yöneten bir yapıdır. Başka bir deyişle, Proxy, temel nesnenin üzerinde gerçekleştirilen işlemlere aracılık eder ve bu işlemleri özelleştirebilir. Proxy, nesnelerin üzerinde yapılan işlemleri (okuma, yazma, çağrılma, vb.) yakalama ve müdahale etme yeteneği sunar.
Proxy Kullanımı
Proxy kullanarak bir nesnenin üzerinde gerçekleştirilen işlemleri yönetmek için, ilk olarak bir Proxy nesnesi oluşturmanız gerekir. İşte basit bir örnek:
const target = {
message: 'Merhaba, Dünya!'
};
const handler = {
get: function (obj, prop) {
return obj[prop].toUpperCase();
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.message); // "MERHABA, DÜNYA!"
Bu örnekte, target
adında bir nesne ve bu nesnenin üzerinde işlemleri yönetecek olan handler
adında bir nesne oluşturduk. Ardından, target
ve handler
nesnelerini kullanarak bir Proxy nesnesi oluşturduk. Proxy nesnesi üzerinden message özelliğine eriştiğimizde, handler
nesnesindeki get işlemi devreye girer ve özelliği büyük harflerle döndürür.
Proxy'nin Kullanıldığı Alanlar
Proxy, aşağıdaki senaryolarda kullanılabilir:
- Veri Doğrulama: Proxy, nesnelerin özelliklerine yazılan değerleri doğrulamak için kullanılabilir.
const user = {
age: 25
};
const validateHandler = {
set: function (obj, prop, value) {
if (prop === 'age' && typeof value !== 'number') {
throw new TypeError('Yaş değeri bir sayı olmalıdır.');
}
obj[prop] = value;
}
};
const userProxy = new Proxy(user, validateHandler);
userProxy.age = 30; // Başarılı
userProxy.age = 'otuz'; // Hata: TypeError: Yaş değeri bir sayı olmalıdır.
Bu örnekte, user
adında bir nesne ve validateHandler
adında bir işlem yöneticisi oluşturduk. Proxy nesnesi, age
özelliğine yazılacak değeri kontrol eder ve eğer değer sayı değilse hata fırlatır.
- Değer Dönüşümü: Proxy, nesnelerin özelliklerinin değerlerini dönüştürmek için kullanılabilir.
const temperature = {
celsius: 25
};
const celsiusToFahrenheitHandler = {
get: function (obj, prop) {
if (prop === 'fahrenheit') {
return (obj.celsius * 9) / 5 + 32;
}
return obj[prop];
}
};
const temperatureProxy = new Proxy(temperature, celsiusToFahrenheitHandler);
console.log(temperatureProxy.fahrenheit); // 77
Bu örnekte, sıcaklık değerlerini içeren bir temperature
nesnesi ve bu değerleri dönüştüren celsiusToFahrenheitHandler
işlem yöneticisi oluşturduk. Proxy nesnesi, sıcaklık değerini Fahrenheit olarak döndürür.
- Reaktiflik ile Proxy Kullanımı: Proxy, JavaScript'te reaktif programlama örneklerinde de kullanılabilir ve herhangi bir framework kullanmadan da durum değişikliklerine yanıt olarak işlemleri yönetebilir.
function reactive(obj, callback) {
const handler = {
get: function (target, prop) {
return target[prop];
},
set: function (target, prop, value) {
target[prop] = value;
callback(prop, value);
return true;
}
};
return new Proxy(obj, handler);
}
const state = {
count: 0
};
const render = (prop, value) => {
console.log(`State değişti: ${prop} = ${value}`);
};
const reactiveState = reactive(state, render);
reactiveState.count++; // State değişti: count = 1
reactiveState.count--; // State değişti: count = 0
Bu örnek, Proxy'nin JavaScript'te reaktif programlama için nasıl kullanabileceğini göstermektedir. Proxy ve işlem yöneticisi kullanarak, nesnelerin özelliklerine yapılan işlemleri yönetebilir ve durum değişikliklerine yanıt olarak geri çağırma işlemlerini tetikleyebiliriz. Bu yaklaşım, geliştiricilere daha fazla esneklik ve kontrol sağlar ve projelerin ihtiyaçlarına göre özelleştirilebilir.
- Özellik Erişimini İzleme: Proxy, nesnelerin özelliklerine erişimi izlemek ve bu erişimleri raporlamak için kullanılabilir.
const person = {
name: 'Ahmet',
age: 30
};
const accessLoggerHandler = {
get: function (obj, prop) {
console.log(`"${prop}" özelliğine erişildi.`);
return obj[prop];
}
};
const personProxy = new Proxy(person, accessLoggerHandler);
console.log(personProxy.name); // "name" özelliğine erişildi.
console.log(personProxy.age); // "age" özelliğine erişildi.
Bu örnekte, person
adında bir nesne ve bu nesnenin özelliklerine erişimi izleyen accessLoggerHandler
işlem yöneticisi oluşturduk. Proxy nesnesi, özelliklere erişildiğinde ilgili bilgileri konsola yazdırır.
- Özellik Değişikliklerini İzleme: Proxy, nesnelerin özelliklerinde gerçekleştirilen değişiklikleri izlemek ve bu değişiklikleri raporlamak için kullanılabilir.
const product = {
price: 100
};
const changeLoggerHandler = {
set: function (obj, prop, value) {
console.log(`"${prop}" özelliği ${obj[prop]} değerinden ${value} değerine değiştirildi.`);
obj[prop] = value;
}
};
const productProxy = new Proxy(product, changeLoggerHandler);
productProxy.price = 120; // "price" özelliği 100 değerinden 120 değerine değiştirildi.
Bu örnekte, product
adında bir nesne ve bu nesnenin özelliklerinde gerçekleştirilen değişiklikleri izleyen changeLoggerHandler
işlem yöneticisi oluşturduk. Proxy nesnesi, özelliklerdeki değişiklikleri konsola yazdırır.
- Sanal Özellikler: Proxy, nesnelere sanal (hesaplanmış) özellikler eklemek için kullanılabilir.
const rectangle = {
width: 10,
height: 20
};
const areaHandler = {
get: function (obj, prop) {
if (prop === 'area') {
return obj.width * obj.height;
}
return obj[prop];
}
};
const rectangleProxy = new Proxy(rectangle, areaHandler);
console.log(rectangleProxy.area); // 200
Bu örnekte, rectangle
adında bir nesne ve bu nesneye sanal bir area
özelliği ekleyen areaHandler
işlem yöneticisi oluşturduk. Proxy nesnesi, area
özelliğine erişildiğinde dikdörtgenin alanını hesaplar ve döndürür.
Proxy özelliği sayesinde, JavaScript'deki nesneler üzerinde güçlü ve esnek işlemler gerçekleştirebilirsiniz. Bu özellik, web uygulamalarının performansını ve güvenliğini artırabilir, kodun okunabilirliğini ve bakımını kolaylaştırabilir. Proxy özelliğini kullanarak, çok sayıda farklı senaryoda işlemleri yönetebilir ve geliştirme sürecini optimize edebilirsiniz.
- Özellik Adlarını Değiştirme: Proxy, nesnelerin özellik adlarını değiştirerek veya takma adlar oluşturarak kullanmak için kullanılabilir.
const student = {
firstName: 'Mehmet',
lastName: 'Yılmaz'
};
const aliasHandler = {
get: function (obj, prop) {
if (prop === 'adi') {
return obj.firstName;
}
if (prop === 'soyadi') {
return obj.lastName;
}
return obj[prop];
}
};
const studentProxy = new Proxy(student, aliasHandler);
console.log(studentProxy.adi); // Mehmet
console.log(studentProxy.soyadi); // Yılmaz
Bu örnekte, student
adında bir nesne ve bu nesnenin özellik adlarını değiştiren aliasHandler
işlem yöneticisi oluşturduk. Proxy nesnesi, adi
ve soyadi
adlarını kullanarak öğrencinin adı ve soyadını döndürür.
- Özelliklere Varsayılan Değer Atama: Proxy, belirli bir özelliğin değeri belirtilmemişse varsayılan değer atamak için kullanılabilir.
const car = {
brand: 'Ford',
model: 'Mustang'
};
const defaultHandler = {
get: function (obj, prop) {
return obj[prop] || 'Bilgi yok';
}
};
const carProxy = new Proxy(car, defaultHandler);
console.log(carProxy.brand); // Ford
console.log(carProxy.color); // Bilgi yok
Bu örnekte, car
adında bir nesne ve bu nesnenin özelliklerine varsayılan değer atayan defaultHandler
işlem yöneticisi oluşturduk. Proxy nesnesi, color
özelliğine erişildiğinde değeri olmadığı için 'Bilgi yok' değerini döndürür.
Proxy özelliği, JavaScript dilinin sunduğu güçlü araçlardan biridir ve modern web uygulamalarında daha esnek ve güvenli bir şekilde çalışmanıza olanak tanır. İyi uygulamalarla birlikte, Proxy özelliğini kullanarak uygulamanızın performansını ve kod kalitesini önemli ölçüde artırabilirsiniz. Bu makalede sunulan örnekler, Proxy'nin kullanım alanlarını ve faydalarını göstermektedir; ancak bu özellik, gerçek projelerde daha karmaşık ve özelleştirilmiş senaryolarda kullanılabilir.
- Fonksiyon Çağrılarını Yönetme: Proxy, fonksiyon çağrılarını yönetmek ve fonksiyonlara ek işlevsellik sağlamak için kullanılabilir.
function greet(name) {
return `Merhaba, ${name}!`;
}
const timingHandler = {
apply: function (target, thisArg, argumentsList) {
console.time('greet');
const result = target.apply(thisArg, argumentsList);
console.timeEnd('greet');
return result;
}
};
const timedGreet = new Proxy(greet, timingHandler);
console.log(timedGreet('Tayfun')); // Merhaba, Tayfun!
Bu örnekte, greet
adında bir fonksiyon ve bu fonksiyonun çağrılma süresini ölçen timingHandler
işlem yöneticisi oluşturduk. Proxy nesnesi ile fonksiyonu çağırdığımızda, işlem süresi konsola yazdırılır.
- Özelliği Okuma ve Yazma İzni Kontrolü: Proxy, nesnelerin belirli özelliklerine erişim izni vererek veya kısıtlayarak kullanılabilir.
const secretData = {
name: 'John Doe',
secretKey: '12345'
};
const accessControlHandler = {
get: function (obj, prop) {
if (prop === 'secretKey') {
throw new Error('Bu özelliğe erişim izniniz yok.');
}
return obj[prop];
},
set: function (obj, prop, value) {
if (prop === 'secretKey') {
throw new Error('Bu özelliği değiştirme izniniz yok.');
}
obj[prop] = value;
}
};
const protectedData = new Proxy(secretData, accessControlHandler);
console.log(protectedData.name); // John Doe
console.log(protectedData.secretKey); // Hata: Bu özelliğe erişim izniniz yok.
protectedData.secretKey = '67890'; // Hata: Bu özelliği değiştirme izniniz yok.
Bu örnekte, secretData
adında hassas bilgiler içeren bir nesne ve bu nesnenin özelliklerine erişimi yöneten accessControlHandler
işlem yöneticisi oluşturduk. Proxy nesnesi ile secretKey
özelliğine erişmeye veya değiştirmeye çalıştığımızda hata alırız.
Proxy özelliği, JavaScript'de nesneler ve fonksiyonlar üzerinde yapılan işlemleri özelleştirmenize ve yönetmenize olanak tanır. Bu makalede sunulan örnekler, Proxy'nin çeşitli kullanım alanlarını ve uygulama senaryolarını göstermektedir. Yine de, bu özellik çok daha karmaşık ve özelleştirilmiş durumlar için kullanılabilir ve projelerinize güçlü ve esnek çözümler sunar.
- Özelliklerin Varlığını Kontrol Etme: Proxy, nesnelerin özelliklerinin varlığını kontrol etmek için kullanılabilir.
const employee = {
name: 'Ayşe',
role: 'Developer'
};
const existenceHandler = {
has: function (obj, prop) {
if (!(prop in obj)) {
console.log(`"${prop}" özelliği bulunamadı.`);
return false;
}
return true;
}
};
const employeeProxy = new Proxy(employee, existenceHandler);
console.log('name' in employeeProxy); // true
console.log('salary' in employeeProxy); // "salary" özelliği bulunamadı. false
Bu örnekte, employee
adında bir nesne ve bu nesnenin özelliklerinin varlığını kontrol eden existenceHandler
işlem yöneticisi oluşturduk. Proxy nesnesi ile salary
özelliğinin varlığını kontrol etmeye çalıştığımızda, konsola mesaj yazdırılır ve false değeri döndürülür.
- Özelliklerin Sıralamasını Değiştirme: Proxy, nesnelerin özelliklerinin sıralamasını değiştirmek için kullanılabilir.
const items = {
apple: 5,
orange: 3,
banana: 2
};
const sortingHandler = {
ownKeys: function (obj) {
return Object.keys(obj).sort((a, b) => obj[a] - obj[b]);
}
};
const sortedItemsProxy = new Proxy(items, sortingHandler);
console.log(Object.keys(sortedItemsProxy)); // ["banana", "orange", "apple"]
Bu örnekte, items
adında bir nesne ve bu nesnenin özelliklerinin sıralamasını değiştiren sortingHandler
işlem yöneticisi oluşturduk. Proxy nesnesi ile nesnenin özelliklerini sıraladığımızda, özellikler değerlerine göre artan sırada döndürülür.
- Proxy ve Reflection: Proxy, JavaScript'teki Reflection API ile birlikte kullanılabilir. Reflection API, nesnelerin yapılarını ve değerlerini programın çalışma süresi boyunca değiştirmenize ve incelemenize olanak tanır. Bu nedenle, Proxy ve Reflection API, nesne ve fonksiyon işlemlerini daha da özelleştirmek ve yönetmek için birlikte kullanılabilir.
const target = {
name: 'John',
age: 25
};
const handler = {
get: function (obj, prop) {
console.log(`"${prop}" özelliği okunuyor.`);
return Reflect.get(obj, prop);
},
set: function (obj, prop, value) {
console.log(`"${prop}" özelliği ${value} değeri ile güncelleniyor.`);
return Reflect.set(obj, prop, value);
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // "name" özelliği okunuyor. John
proxy.age = 26; // "age" özelliği 26 değeri ile güncelleniyor.
Bu örnekte, target
adında bir nesne ve bu nesnenin özelliklerine erişimi yöneten handler
adında bir işlem yöneticisi oluşturduk. Proxy ile target
nesnesine eriştiğimizde, işlem yöneticisi get ve set metodlarını kullanarak özelliklere erişim işlemlerini yönetir.
Özelliklere erişirken, Reflect.get
ve Reflect.set
işlemlerini kullanarak Reflection API ile birlikte Proxy'yi kullanıyoruz. Bu sayede, nesnelerin özelliklerine yapılan işlemleri daha güçlü ve esnek bir şekilde yönetebiliriz.
Sonuç
Proxy özelliği, JavaScript dilinde güçlü ve esnek bir araçtır. Bu makalede sunulan örnekler, Proxy'nin çeşitli kullanım alanlarını ve uygulama senaryolarını göstermektedir, ancak bu özellik, gerçek projelerde daha karmaşık ve özelleştirilmiş senaryolarda kullanılabilir. Proxy'nin kullanımı ile nesneler ve fonksiyonlar üzerinde yapılan işlemleri yönetebilir, durum değişikliklerine yanıt olarak işlemleri yönetebilir ve uygulamanızın performansını ve esnekliğini önemli ölçüde artırabilirsiniz.