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