Unlock Powerful JavaScript Proxy Tricks: Getters, Validation, Logging & Dynamic APIs
This article explains how JavaScript Proxy can intercept object operations to implement getter/setter shortcuts, dynamic validation, logging, and flexible API proxies, providing clear code examples and practical scenarios for both front‑end and Node.js development.
Proxy provides a way to wrap an object, allowing developers to intercept various operations through traps defined in a handler.
Common use cases include:
Getter/Setter
Validation/Filtering
Logging/Statistics
Dynamic proxy
The supported handler traps are getter/setter, function call/construct, the in and delete operators, and property‑related operations such as Object.defineProperty and Object.getPrototypeOf. See MDN Proxy documentation for the full list.
Getter/Setter
Example of using a plain object with a setter to collect values:
const language = {
set current(name) {
this.log.push(name);
},
log: []
};
language.current = 'EN';
language.current = 'FA';
console.log(language.log); // ["EN","FA"]Using Proxy simplifies batch and anonymous getter/setter logic:
const language = new Proxy({ log: [] }, {
set(target, key, value) {
if (key === 'current') {
target.log.push(value);
}
}
});
language.current = 'EN';
language.current = 'FA';
console.log(language.log); // ["EN","FA"]Validation/Filtering
Proxy traps can perform dynamic type checking:
const schema = { name: 'string', age: 'number', gender: 'string' };
const person = new Proxy({}, {
set(target, key, value) {
if (key in schema && typeof value === schema[key]) {
target[key] = value;
}
// otherwise ignore or throw error
}
});
person.name = 'Alan';
person.age = 22;
person.gender = 1234; // ignored
console.log(person); // { name: 'Alan', age: 22 }Similar checks can be applied in constructors or other traps.
Logging/Statistics
By intercepting the set trap you can log every property change:
const data = { name: 'The Devil wears Prada', author: 'Lauren Weisberger' };
const proxy = new Proxy(data, {
set(target, key, value) {
console.log('set', key, ':', target[key], '->', value);
target[key] = value;
}
});
proxy.name = 'Notebook';
proxy.name = 'asdf';Dynamic Proxy (API Wrapper)
A concise 20‑line proxy can create a flexible API client:
const axios = require('axios');
const instance = axios.create({ baseURL: 'http://localhost:3000/api' });
const METHODS = ['get','post','patch'];
const api = new Proxy({}, {
get(_, name) {
return new Proxy({}, {
get(_, method) {
return METHODS.includes(method) && new Proxy(() => {}, {
apply(_, __, [config]) {
return instance.request({ url: name, method, ...config });
}
});
}
});
}
});
// Usage:
// api.user.get({ params: { id: 12 } }).then(console.log).catch(console.error);
// api.register.post({ body: { username: 'xxx', password: 'xxxx' } }).then(console.log).catch(console.error);This pattern resembles the Mediator design pattern, allowing Proxy to act as an intermediary that provides a uniform interface without defining explicit relationships between objects. It can also be leveraged for hot‑reloading by swapping the target module behind a Proxy.
Node Underground
No language is immortal—Node.js isn’t either—but thoughtful reflection is priceless. This underground community for Node.js enthusiasts was started by Taobao’s Front‑End Team (FED) to share our original insights and viewpoints from working with Node.js. Follow us. BTW, we’re hiring.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
