meta programming in
What is meta-programming?
- Code generation
- Self-modifying code
- Code that inspects itself
writing code that writes code
Meta programing
in es5
some meta programming features have been in javascript since the beginning of the language
- eval (ECMAScript 1st Edition)
- getOwnPropertyNames (ECMAScript 5.1)
EVAL
In my opinion, it is Douglas Crockford who is evil
meta programing
in es6
Proxy
The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc)
A proxy is like middleware for an object
{ k: "v" }
get
set
myObject.k
JavaScript Objects
Objects have a low-level api
get: retrieve a value associated with a key
set: set a value associated to a key
Enumerate Keys: object.keys, for .. in ..
delete: removes a key and value
{ k: "v" }
get
set
myObject.k
list of hooks into an object through a proxy
Traps
So, what is the name of a hook (singular) into an object through a proxy?
[Audience Participation]
Traps
getPrototypeOf //Object.getPrototypeOf
setPrototypeOf //Object.setPrototypeOf
isExtensible //Object.isExtensible
defineProperty //Object.defineProperty
has //foo in object
get //object.foo, object[foo]
set //object.foo = bar, object[foo] = bar
deleteProperty //delete object.foo, delete object[foo]
enumerate //for keys in object
ownKeys //Object.keys
apply //Function.prototype.apply
construct //new object(..args)
Reflect
Similar to a Proxy but through a built-in object
- does not construct new objects
- has exact same traps as proxy
Reflect
Also, other reflective stuff from around the language is packaged up in one place
Reflect is effectively a collection of all of those “internal methods” that were available exclusively through the JavaScript engine internals, now exposed in one single, handy object.
Reflect
var ages = [11, 33, 12, 54, 18, 96];
// Function.prototype style:
var youngest = Math.min.apply(Math, ages);
var oldest = Math.max.apply(Math, ages);
var type = Object.prototype.toString.call(youngest);
// Reflect style:
var youngest = Reflect.apply(Math.min, Math, ages);
var oldest = Reflect.apply(Math.max, Math, ages);
var type = Reflect.apply(Object.prototype.toString, youngest);
Proxy code time
Constructing a Proxy
const myObject = {
foo: 'bar'
}
const myHandler = {
get: (target, property) => 'hello world... of proxies!'
}
const myObjectProxy = new Proxy(myObject, myHandler)
myObjectProxy.anyThingYouWant //'hello world... of proxies!'
new Proxy(target, handler)
- target: the object to be proxied
- handler: the set of traps
Constructing a Proxy
const myObject = {
anEmptyVessel: 'Jar'
}
const myHandler = {
get: (target, property) => `${target[property]} ${target[property]}`
}
const myObjectProxy = new Proxy(myObject, myHandler)
myObjectProxy.anEmptyVessel //'Jar Jar'
new Proxy(target, handler)
- target: the object to be proxied
- handler: the set of traps
Reflect code time
Used to do similar things as Proxy, but through a built-in object
myObject = {}
Reflect.set(myObject, 'foo', 'bar') //true
myObject.foo //bar
Another simple reflect example
Reflect.has({x: 0}, 'x'); // true
Reflect.has({x: 0}, 'y'); // false
Using a proxy to do something neat
protecting properties
var target = TouchHandler(['longPress', 'swipe', 'force')
var handler = {
set: function (target, property, value) {
if(property === 'force'){
throw new Error("That's not how the force works!");
}
return target[property] = value
}
};
var proxy = new Proxy(target, handler);
auto-populating properties
function Tree() {
return new Proxy({}, handler);
}
var handler = {
get: function (target, key, receiver) {
if (!(key in target)) {
target[key] = Tree(); // auto-create a sub-Tree
}
return Reflect.get(target, key, receiver);
}
};
const fear = Tree()
fear.anger.hate = "suffering"
//{ anger: { hate: "suffering" } }
"Useful" proxy uses
- Hiding private properties
- onChange event for Objects or Arrays
- Caching of properties
- Data validation rules
- property 'access control'
- measuring performance of operations
References
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Meta_programming
- http://dealwithjs.io/es6-features-10-use-cases-for-proxy/
- http://lucasfcosta.com/2016/11/15/Meta-Programming-in-JavaScript-Part-Three.html
- https://hacks.mozilla.org/2015/07/es6-in-depth-proxies-and-reflect/
Thanks!
Javascript Meta Programming
By Michael Jasper
Javascript Meta Programming
- 984