JavaScript Metaprogramming
Introduction
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.
Examples
console.log(eval("5 + 2")) // 7
const obj = {
hello() {
console.log("Hello!")
},
}
// Meta level
for (const key of Object.keys(obj)) {
console.log(key)
}
All Object.* methods can be considered metaprogramming functionality
Kinds of metaprogramming
Reflective metaprogramming means that a program processes itself. Kiczales et al2. [2] distinguish three kinds of reflective metaprogramming:
- Introspection: you have read-only access to the structure of a program.
- Self-modification: you can change that structure
- Intercession: you can define the semantics of some language operations
Examples
Introspection
Object.keys() performs introspection
self-modification
The following function moveProperty
moves a property from a source to
a target. It performs self-modification via the bracket operator for
property access, the assignment operator and the delete operator. (In
production code, you’d probably use property descriptors for this task.)
function moveProperty(source, propertyName, target) {
target[propertyName] = source[propertyName]
delete source[propertyName]
}
const obj1 = { prop: "abc" }
const obj2 = {}
moveProperty(obj1, "prop", obj2)
console.log(obj1) // {}
console.log(obj2) // { prop: 'abc' }
intercession
ECMAScript 5 doesn't support intercession. Proxies were created to fill that gap.
Footnotes
- Don't ever use eval. If you think you're a clever clogs that can work your away around the obvious security issues, then you especially should not use eval.↩
- "The Art of the Metaobject Protocol" by Gregor Kiczales, Jim des Rivieres and Daniel G. Bobrow. Book, 1991.↩