Understanding JavaScript Proxy Objects

Rehmat Sayany
3 min readJan 9, 2024

Introduction

JavaScript Proxy objects are a powerful and flexible feature that allows you to intercept and customize operations performed on objects. Introduced in ECMAScript 6 (ES6), Proxy objects provide a mechanism to control the behavior of fundamental operations on objects, enabling advanced use cases and improved security.

Basics of Proxies

A Proxy is created with two main components: a target object and a handler. The target object is the original object you want to intercept operations on, and the handler is an object containing methods called traps, which define custom behavior for these operations.

Creating a Proxy

const targetObject = {
name: 'John',
age: 25,
};
const handler = {
get(target, prop) {
console.log(`Getting property ${prop}`);
return target[prop];
},
};
const proxy = new Proxy(targetObject, handler);console.log(proxy.name); // Output: Getting property name, John

In this example, the get trap intercepts property access and logs a message before returning the actual property value.

Understanding Targets, Props, and Values

  • Target: The target is the original object that the Proxy wraps around. In the example above, targetObject is the target.
  • Prop (Property): Prop represents the property being accessed on the object. In the get trap, prop is the name of the property being accessed.
  • Value: Value refers to the value assigned to a property. In the set trap, value is the new value being assigned to a property.

Common Methods in Handlers

1. get(target, prop, receiver)

The get trap intercepts property access and allows you to customize the behavior when reading a property.

2. set(target, prop, value, receiver)

The set trap intercepts property assignment and enables you to validate or modify the assigned value.

3. has(target, prop)

The has trap is triggered when using the in operator to check if a property exists in an object.

4. deleteProperty(target, prop)

The deleteProperty trap is called when using the delete operator to remove a property from an object.

5. apply(target, thisArg, argumentsList)

The apply trap is invoked when a Proxy is used as a function.

Use Cases of Proxy Objects

1. Validation

Proxies can be used to enforce constraints on data by validating or modifying property values.

const validatedUser = new Proxy({}, {
set(target, prop, value) {
if (prop === 'age' && (typeof value !== 'number' || value < 0 || value > 120)) {
throw new Error('Invalid age');
}
target[prop] = value;
return true;
},
});
validatedUser.age = 30; // Valid assignment
validatedUser.age = -5; // Throws an error: Invalid age

2. Logging

Proxies enable easy logging of property access, providing insights into object usage for debugging or performance monitoring.

const loggedObject = new Proxy({}, {
get(target, prop) {
console.log(`Accessing property: ${prop}`);
return target[prop];
},
});
loggedObject.name = 'Alice'; // Accessing property: name
console.log(loggedObject.name); // Accessing property: name

3. Security

Proxies can enhance object security by preventing unauthorized access to certain properties or operations.

const securedObject = new Proxy({ secret: 'classified' }, {
get(target, prop) {
if (prop === 'secret') {
throw new Error('Unauthorized access');
}
return target[prop];
},
});
console.log(securedObject.publicInfo); // Access allowed
console.log(securedObject.secret); // Throws an error: Unauthorized access

4. Memoization

Proxies can be used for memoization, caching the results of expensive function calls for better performance.

function fibonacci(n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
const memoizedFibonacci = new Proxy({}, {
get(target, prop) {
if (!(prop in target)) {
target[prop] = fibonacci(Number(prop));
}
return target[prop];
},
});
console.log(memoizedFibonacci[10]); // Calculated and cached
console.log(memoizedFibonacci[5]); // Retrieved from cache

Real-time Example in E-commerce

Consider an e-commerce scenario where you want to enforce some business rules using Proxy objects.

const product = {
name: 'Smartphone',
price: 500,
quantity: 10,
};
const securedProduct = new Proxy(product, {
set(target, prop, value) {
if (prop === 'quantity' && value < 0) {
throw new Error('Invalid quantity');
}
target[prop] = value;
return true;
},
});
securedProduct.quantity = 15; // Valid assignment
securedProduct.quantity = -5; // Throws an error: Invalid quantity

In this example, the Proxy ensures that the quantity of product cannot be set to a negative value, enforcing a business rule within the e-commerce context.

Conclusion

JavaScript Proxy objects provide a versatile tool for creating dynamic and customizable behavior around objects. Whether used for validation, logging, security, or performance optimization, proxies empower developers with fine-grained control over object interactions. Understanding and leveraging Proxy objects can lead to cleaner, more maintainable, and secure code in a variety of real-world scenarios.

--

--

Rehmat Sayany

Full Stack developer @westwing passionate about NodeJS, TypeScript, React JS and AWS.