wiki/content/20201022095438-javascript_metaprogramming.md

92 lines
2.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: b866160c-ac93-45af-8faf-1fd40f002f77
title: 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
An example of this is
[eval](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)[^1]:
``` javascript
console.log(eval("5 + 2")); // 7
```
``` javascript
const obj = {
hello() {
console.log("Hello!");
},
};
// Meta level
for (const key of Object.keys(obj)) {
console.log(key);
}
```
All [Object.\*
methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#)
can be considered metaprogramming functionality
# Kinds of metaprogramming
Reflective metaprogramming means that a program processes itself.
Kiczales et al[^2]. \[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
## Introspection
[Object.keys()](20200826201605-objects.org::*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, youd probably use property descriptors for this task.)
``` javascript
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](20201022094207-javascript_proxies) were created to fill that
gap.
# Footnotes
[^1]: 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.
[^2]: "[The Art of the Metaobject
Protocol](http://mitpress.mit.edu/books/art-metaobject-protocol)" by
Gregor Kiczales, Jim des Rivieres and Daniel G. Bobrow. Book, 1991.