Proxies in ES6
What are proxies?
Proxies enable you to intercept and customize operations performed on objects (such as getting properties). They are a metaprogramming feature.
Programming vs metaprogramming
In programming, there are levels:
- At the base level (also called: application level), code processes user input.
- At the meta level, code processes base level code.
The classic example for this is the eval () function, which lets you evaluate/compile JavaScript code on the fly.
Other JavaScript operations may not look like metaprogramming, but actually are, if you look closer:
// Base level
const obj = {
hello() {
console.log('Hello!');
}
};
// Meta level
for (const key of Object.keys(obj)) {
console.log(key);
}
Metaprogramming: Programming with the ability to treat programs as data. It enables expressing certain solution better, or allows greater flexibility in handling new situations without modification.
Kinds of metaprogramming:
- Introspection: you have read-only access to the structure of a program (ES3/5)
- Self-modification: you can change the structure (ES3/5)
- Intercession: you can redefine the semantics of some language operations (ES2015 Proxies)

Source : https://kangax.github.io/compat-table/es6/#test-Proxy


But still, what's so special about these proxies
1. Proxies enable you to intercept and customize operations performed on objects ( such as getting, setting properties, invoking functions and others). They overload operators such as '.' and 'new'.
2.Proxies are a metaprogramming feature
3.Proxies let you do awesome things, which are otherwise impossible.
Sematics and terminology
-
target: object to proxy
-
handler: proxy definition, containing operation traps
- trap: method intercepting an operation on the target



//manipulating dom events
let view = new Proxy({
selected: null
},
{
set: function(obj, prop, newval) {
let oldval = obj[prop];
if (prop === 'selected') {
if (oldval) {
oldval.setAttribute('aria-selected', 'false');
}
if (newval) {
newval.setAttribute('aria-selected', 'true');
}
}
// The default behavior to store the value
obj[prop] = newval;
}
});
let i1 = view.selected = document.getElementById('item-1');
console.log(i1.getAttribute('aria-selected')); // 'true'
let i2 = view.selected = document.getElementById('item-2');
console.log(i1.getAttribute('aria-selected')); // 'false'
console.log(i2.getAttribute('aria-selected')); // 'true'//Value correction and an extra property
let products = new Proxy({
browsers: ['Internet Explorer', 'Netscape']
},
{
get: function(obj, prop) {
// An extra property
if (prop === 'latestBrowser') {
return obj.browsers[obj.browsers.length - 1];
}
// The default behavior to return the value
return obj[prop];
},
set: function(obj, prop, value) {
// An extra property
if (prop === 'latestBrowser') {
obj.browsers.push(value);
return;
}
// Convert the value if it is not an array
if (typeof value === 'string') {
value = [value];
}
// The default behavior to store the value
obj[prop] = value;
}
});
console.log(products.browsers); // ['Internet Explorer', 'Netscape']
products.browsers = 'Firefox'; // pass a string (by mistake)
console.log(products.browsers); // ['Firefox'] <- no problem, the value is an array
products.latestBrowser = 'Chrome';
console.log(products.browsers); // ['Firefox', 'Chrome']
console.log(products.latestBrowser); // 'Chrome'The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).
Thank you for your attention !
Proxies
By Robert Pop
Proxies
- 119