#Create dynamic objects in a nodejs6 REPL with Proxy
Nodejs 6.x comes with ES6 Proxy support baked in. Just like Ruby's method-missing (aka ghost methods), you can intercept getters and setters on an object and, like ActiveRecord in Rails, write rich APIs that can take any method or property name you like.
They are particularly fun in a REPL, where you might want to handle undefined variables.
For example, say we started a nodejs REPL via:
const repl = require('repl')
const evaluator = require('./evaluator')
const replServer = repl.start({ prompt: '>', eval: evaluator })Then we could intercept get requests in the REPL by a custom evaluator.js:
const vm = require('vm')
let sandbox
module.exports = (cmd, context, filename, callback) => {
const contextProxy = {
get(target, name) {
// first check nodejs globals, and return if any
if (name in global) return global[name]
// failing that, if the target has the named property (in this case our REPL context), return it
else if (name in target) return target[name]
// otherwise, do whatever you want
else // ...
}
}
// memoize a new vm sandbox around a Proxy wrapping the context
sandbox = sandbox || vm.createContext(new Proxy(context, contextProxy))
// execute the command in context, and async return
const result = vm.runInContext(cmd, sandbox)
callback(null, result)
}This excerpt comes from my node-keyboard project.
For a deep-dive into the power of Proxy, Symbol and Reflect, check out Keith Cirkel's great series: https://www.keithcirkel.co.uk/metaprogramming-in-es6-symbols/
###Caution!
Use Proxy sparingly. Accessors are much slower than on regular objects. On some benchmarks I ran, they were 100x slower than regular object getters, and 30x slower than Object constructor getters.
Try for yourself https://github.com/justinjmoses/node-es6-proxy-benchmark
