Proxy Traps
We went over Proxy
and how it handles or intercepts incoming operations to a target object in the last blog post. Handler functions are called traps because they trap calls to the target object.
Thirteen internals traps were introduced in ES2015.
Internal Method | Handler Method |
---|---|
[[GetPrototypeOf]] | getPrototypeOf |
[[SetPrototypeOf]] | setPrototypeOf |
[[IsExtensible]] | isExtensible |
[[PreventExtensions]] | preventExtensions |
[[GetOwnProperty]] | getOwnPropertyDescriptor |
[[DefineOwnProperty]] | defineProperty |
[[HasProperty]] | has |
[[Get]] | get |
[[Set]] | set |
[[Delete]] | deleteProperty |
[[OwnPropertyKeys]] | ownKeys |
[[Call]] | call |
[[Construct]] | construct |
You can read more and see the list here.
We will not go over all of them but a few that you would use frequently.
Get, Set & Delete
Get, Set and Delete are relatively straightforward. They allow you to read, write and remove from the target object.
const target = {
id: 1,
name: "John Doe",
age: 42,
income: 70000,
hobby: "Dancing"
};
const handler = {
get: function (target, property) {
if (["age", "income"].includes(property)) {
return `Access Denied, ${property} is restricted.`;
}
return Reflect.get(...arguments);
},
set: function (target, property, value) {
if (property === "name") {
target[property] = `${value} Doe`;
} else {
target[property] = value;
}
return true; // set and delete should return true or false based on the success
},
deleteProperty: function (target, property, value) {
if (property === "id") {
throw new Error("Required Property. Cannot Delete.");
}
delete target[property];
return true; // set and delete should return true or false based on the success
}
};
const proxy = new Proxy(target, handler);
// Get
console.log(proxy.name); // John Doe
console.log(proxy.age); // Access Denied, age is restricted.
console.log(proxy.income); // Access Denied, income is restricted.
console.log(proxy.hobby); // Dancing
// Set
proxy.name = "Jane"
proxy.age = 40;
console.log(proxy.name); // Jane Does
console.log(proxy.age); // Access Denied, age is restricted.
console.log(target.age); // 40
// Delete
console.log(delete proxy.id); // Required Property. Cannot Delete.
console.log(proxy.id); // 1
console.log(delete proxy.hobby); // true
console.log(proxy.hobby); // undefined
ownKeys
Object.keys
or for..in
loops are intercepted by ownKeys
.
const target = {
id: 1,
name: "John Doe",
age: 42,
income: 70000,
hobby: "Dancing"
};
const handler = {
ownKeys: (target, property, value) => {
return Object.keys(target); // returns all keys from object
}
};
const proxy = new Proxy(target, handler);
for (let key in proxy) {
console.log(key); // id, name, age, income, hobby
}
We can use filter
to filter out values (like sensitive information).
const target = {
id: 1,
name: "John Doe",
age: 42,
income: 70000,
hobby: "Dancing"
};
const handler = {
ownKeys: (target, property, value) => {
return Object.keys(target).filter((value) => !["age", "income"].includes(value));
}
};
const proxy = new Proxy(target, handler);
for (let key in proxy) {
console.log(key); // id, name, hobby
}
has
The has
trap intercepts in
calls.
const budget = {
"minimum": 500,
"maximum": 10000
};
const handler = {
has(target, property) {
return property >= budget.minimum && property <= budget.maximum;
}
};
const expenseRange = new Proxy(budget, handler);
console.log(5000 in expenseRange); // true
console.log(10001 in expenseRange); // false