Primer on Metaprogramming in Javascript
Metaprogramming sounds more complicated than it is. Essentially, it’s the ability of a program to modify itself or other programs. Code generation is the quintessential example, but metaprogramming goes deeper to meet more needs.
In addition to metaprogramming after execution, as is done with code generation, Javascript has the ability to lend more structure and control to metaprogramming. Instead of calling this something silly yet intuitive like metametaprogramming, we call this reflection.
Javascript has very explicit metaprogramming built in, albeit introduced more recently than ES1 (the first version of Javascript), and in part due to discussion on the es-discuss mailing list (https://mail.mozilla.org/listinfo/es-discuss), I’ve become aware of the opportunities I’d missed by not using Reflect and Proxy for metaprogramming.
Reflect
There’s some useful, but very not helpful, documentation on reflect on MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect).
You may remember __proto__ as the means to get the prototype object for an object. Now, you can use Reflect.getPrototypeOf(). More importantly, you can use Reflect.setPrototypeOf(). In addition to setting the prototype of the object, thus changing its behavior, this use of Reflect highlights it’s primary use; changing objects on the fly without issue. Want to provide context to an element assignment? Use Reflect.set() to give a context for any this references. Want to make sure that a function is applied despite attempts to overload? Use Reflect.apply().
By taking object operations away from the object themselves, Reflect provides more flexibility and reliability to the manner in which objects and their flow can be manipulated. Though, there’s a yet more organized way that reflect can work, and it involves Proxy.
Proxy
The MDN documentation for Proxy (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) is substantially more useful than Reflect’s documentation, but just due to the examples.
While you can’t overload operators in Javascript as nicely as I’d like, Proxy provides some functionality in this style. If you want to give special consideration to something like assignment, you can use Proxy to define special cases for actions like apply, new, get, set, has, delete, among others. Instead of overloading, though, they’re calling these operations traps.
With reflect, proxy can also reference, use, or alter default methods for an object.
Consider Metaprogramming
Let’s take a word of advice from metaprogramming and not explicitly define when to use it. Instead, if you’re like me, you spend some amount of time in BASH or similar writing code that makes other code, or find yourself thinking something along the lines of “I need to do ___ but just a little differently depending on __”, think if the metaprogramming/reflection tools in Javascript (or whatever your language is; find a guide) can meet the need.