Hi i'm Craig
I do JS AT
You can find me ON the interWebz:
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/3509454/trademe-logo-tagline.png)
PROXIES ROCK
(sies)
![](http://pngimg.com/uploads/stone/stone_PNG13622.png)
![](https://static1.squarespace.com/static/5138a0c6e4b08ef26b567a88/t/51a3d8f9e4b020a19ed61d6a/1369692413720/rocks+alone.png)
What Do I mean by proxy?
Not a web proxy
An ES2015 Proxy object
![](https://img05.deviantart.net/f04b/i/2017/118/0/f/geode_png_by_flowerpowerstock-db7fy7k.png)
Spec?
Support?
Wat is it?
Proxies are a meta-programming feature that allow you to change how fundamental JS operations work on a target object.
By default, they don't do much:
let target = {};
let handlers = {};
let proxy = new Proxy(target, handlers);
console.log(proxy.foo); // undefined
![](https://www.wildwestmotorsportspark.com/wp-content/uploads/2016/03/rocks-foreground.png)
Meta-programming?
function createFunction (name) {
return `
(function () {
return function ${name} () {
console.log('hello ${name}!');
return createFunction('${name}');
}
})()
`;
}
eval(createFunction('Craig'))();
Programs operate on data and data structures.
Meta-programs operate on programs:
![](https://s-media-cache-ak0.pinimg.com/originals/cb/31/70/cb31703ce0840b2ba4b7ef6332536f86.png)
Meta-programming
![](http://dmlapidary.org/portals/0/!Resources/Images/Rocks/GeodeDugway-v01-c360x360d120q24.png)
Object.keys();
function barify (object, key) {
object[key] = 'bar';
}
function doMaths (a, b, c) {
return a * b + c;
}
doMaths.length; // 3
A ProxY provides a mechanism for changing JS operations at runtime!
What does that look like?
let object = {};
let handlers = {};
let proxy = new Proxy(object, {
get (target, key) {
console.log(target, key);
}
});
proxy.foo; // object, 'foo'
Here we have provided a trap for the "get" operation. Whenever a property is accessed on our object, the trap will fire.
What kind of traps are there?
![](http://i.imgur.com/vZPbNqs.png)
get
set
has
deleteProperty
defineProperty
getOwnPropertyDescriptor
ownKeys
getPrototypeOf
setPrototypeOf
isExtensible
preventExtensions
set:
let manners = new Proxy({}, {
set (target, key, value) {
console.log(target, key, value);
if (value.match(/please$/)) {
Reflect.set(target, key, value);
} else {
console.log('nah');
}
}
});
manners.foo = 'bar'; // 'nah';
manners.foo = 'bar, please';
has:
let object = { foo: 'bar' };
let liar = new Proxy(object, {
has (target, prop) {
return !Reflect.has(target, prop);
}
});
console.log('foo' in liar); // false;
console.log('baz' in liar); // true;
Note that in these examples we've used the Reflection API. Every Proxy trap has an equivalent method on the global Reflect object (also part of ES2015)
deleteProperty:
let object = { foo: 'bar' };
let hoarder = new Proxy(object, {
deleteProperty (target, prop) {
return false;
}
});
delete hoarder.foo;
console.log(hoarder.foo); // 'bar'
![](https://upload.wikimedia.org/wikipedia/en/thumb/5/5c/The_Rock_FM_New_Zealand_logo.svg/1200px-The_Rock_FM_New_Zealand_logo.svg.png)
Function only traps:
apply:
construct:
var func = function () { };
var trapped = new Proxy(func, {
apply () {
console.log('Hello?');
},
construct () {
console.log('What do you want?');
}
});
console.log(trapped()); // 'Hello?'
console.log(new trapped()); // 'What do you want?'
Invariants:
If the following invariants are violated, the proxy will throw a TypeError:
- A property cannot be added, if the target object is not extensible.
- A property cannot be added as or modified to be non-configurable, if it does not exists as a non-configurable own property of the target object.
- A property may not be non-configurable, if a corresponding configurable property of the target object exists.
- If a property has a corresponding target object property then Object.defineProperty(target, prop, descriptor) will not throw an exception.
- In strict mode, a false return value from the defineProperty handler will throw a TypeError exception.
A trap may have a set of invariants, which are rules around behaviour that cannot be modified.
For example, the deleteProperty trap:
WHY?
![](https://orig12.deviantart.net/b6dd/f/2014/196/9/0/nickelback_with_logo_png_by_nickelbackloverxoxox-d7qvaqh.png)
Real use cases?
and more...
My use case:
let mock = ineeda();
// [[Get]] trap:
console.log(mock.foo.bar.baz); // Proxies all the way down.
// [[Apply]] trap:
console.log(mock.foo.bar.baz()); // throws Error('Not implemented');
// [[Set]] trap:
mock.value = 42;
console.log(mock.value) // 42;
// Whole bunch of traps:
sinon.stub(mock.some.deeply.nested, 'property');
What can't they do?
![](https://cdn0.rubylane.com/shops/551702/1961.1L.jpg)
Proxies are powerful, but they aren't omnipotent
Missing traps?
function Point (x, y) {
return new Proxy({ x, y }, {
add (a, b) {
return new Proxy(a.x + b.x, a.y + b.y);
}
});
}
var p1 = Point(1, 2);
var p2 = Point(3, 4);
console.log(p1 + p2); // { x: 4, y: 6 }
operator overloading:
Note: unfortunately, this isn't real JS 😢
Missing traps?
var object = {};
var falsy = new Proxy(object, {
toBoolean (target) {
return false;
}
});
console.log(!!object); // true;
console.log(!!falsy); // false;
toBoolean:
Note: unfortunately, this isn't real JS 😢
FIN
![](https://static.tumblr.com/292f6ea2666fc3a44512b3a389080fb2/doudh2y/B5Onkc30h/tumblr_static_tumblr_static_chkoiuuwjn4s8k4csk0w480k8_640.gif)
![](http://cdn.bulbagarden.net/upload/f/fc/BrockAG.png)
Questions?
Proxies rocksies
By Craig Spence
Proxies rocksies
ES2015 Proxies
- 3,162