JavaScript Meta Programming
Metaprogramming
Metaprogramming refers to a number of ways aprogram can manipulate itself:
- Modify objects at runtime
- Inspect objects at runtime
- Control objects at runtime
- Intercept running operations
- Modify functions, and classes
- Generate dynamic code
The Easy Explanation
Normally,code handles data.
With metaprogramming,code handles code.
Inspecting Objects
With the methodObject.keys() you caninspect object properties.
UsingObject.keys() is a simple example of metaprogramming.
Example
This code is analyzing another piece of code (an object):
const user = {name: "Jan", age: 40};
// Fill Array with Object keys
const myArr = Object.keys(user);
Modify Objects
I typical metaprogramming task is tomodify object behaviour:
Example
const person = {name: "John", age: 41};
// Define "name" to return "secret"
Object.defineProperty(person, "name", {
get() { return "secret"; }
});
let name = person.name;
Generate Dynamic Code
Metaprogramming involves dynamic code generation.
JavaScript cangenerate functions at runtime:
Metaprogramming Examples
| Consept | Description |
|---|---|
| Validation | Restrict the values that can be set to a property |
| Logging | Display property changes using a Proxy |
| Debugging | Intercept an operation using a Proxy |
| Frameworks | Vue, MobX, and Svelte use metaprogramming to detect state changes |
| ORM / database mapping | Wrap objects and creates fields based on database schema |
| Dynamic APIs | Create functions or object structures at runtime |
Proxy Metaprogramming
The two objectsProxy andReflect allow for programming at the meta level in JavaScript.
Proxy can be used tointercept property operations like reading or writing.
In the example below:
- A user object iswrapped in a Proxy
- The Proxy uses aset() trap to log whenever a property is set
Example
Log changes to property values:
const user = {name: "Jan", age: 40};
// Wrap the Object in a Proxy
const proxy = new Proxy(user, {
// Use a set trap
set(target, property, value) {
// Log changes
log(property + "; " + value);
return target[property];
}
});
// Change Properties
proxy.name = "John";
proxy.age = 45;
proxy.name = "Paul";
Proxy with Reflect
Reflect makes Proxy behavior match normal object behavior
In the example below:
- A user object iswrapped in a Proxy
- The Proxy uses aset() trap to log when a property is set
- The set trap usesReflect.set() for safe forwarding
Example
Log changes to property values:
const user = {name: "Jan", age: 40};
// Wrap the Object in a Proxy
const proxy = new Proxy(user, {
// Use a set trap
set(target, property, value) {
// Log changes
log(property + ": " + value);
// Safe forwarding with Reflect
return Reflect.set(target, property, value);
}
});

