What is metaprogramming?
Wikipedia:
meta programming (meta programming) is a programming technique in which a computer program written can treat other programs as data.
Means that such a program can write: it can
read generation, analysis or other conversion programs, even
modify the program runs itself (reflection).
The concept of element in metaprogramming can be understood as the program itself. Metaprogramming focuses on the following points or points:
1. Modify the language structure at runtime. This phenomenon is called
reflection programming or
reflection;
- introspection : code inspection yourself;
- self-modification : the code modifies itself;
- mediates : the code modifies the default language behavior of
affects other codes;
- 2. Generate code;
One, introspection
The code can self-check, access internal attributes, and get the underlying information of the code!
// 访问对象自身属性
var users = {
'Tom': 32,
'Bill': 50,
'Sam': 65
};
Object.keys(users).forEach(name => {
const age = users[name];
console.log(`User ${name} is ${age} years old!`);
});
// 输出结果
User Tom is 32 years old!
User Bill is 50 years old!
User Sam is 65 years old!
introspection is very common in usual business development, which is also a use of meta-programming technology!
Two, self-modification
As the name implies, the code can modify its own attributes or other underlying information!
let a = 1;
if (a == 1 && a == 2 && a == 3) {
console.log("元编程");
}
The above code cannot meet the conditional output in any case under normal circumstances.
Because it is impossible for a value to be equal to 1, 2, and 3 at the same time; however, it can be achieved using metaprogramming:
// 修改自身
let a = {
[Symbol.toPrimitive]: ((i) => () => ++i)(0);
}
if (a == 1 && a == 2 && a == 3) {
console.log("元编程");
}
// 输出 '元编程'
Symbol.toPrimitive is a built-in Symbol value, which exists as a function value attribute of the object;
It will be called when the object is converted to the original value. The initial value is 1, and +1 is called once to satisfy a == 1 && a == 2 && a == 3
;
The above function is transformed into:
let a = {
[Symbol.toPrimitive]: (function (i){
return function (){
return ++i
}
})(0)
}
if (a == 1 && a == 2 && a == 3) {
console.log("元编程");
}
In the development process, self-modification should be avoided as much as possible. It is conceivable that when a data is being used and the data is modified at the same time, it is easy to cause unexpected errors afterwards!
3. Mediation
Code modifies the default language behavior and affects other codes. The most obvious manifestation is to change the semantics of other objects!
In metaprogramming, the concept of mediation is similar to packaging, capturing, and intercepting.
Object.defineProperty()
is a typical mediation application:
var sun = {};
Object.defineProperty(sun, 'rises', {
value: true,
configurable: false,
writable: false,
enumerable: false
});
console.log('sun rises', sun.rises);
sun.rises = false;
console.log('sun rises', sun.rises);
// 输出
sun rises true
sun rises true
In the above example, a new common object sun
, and then Object.defineProperty
changed by 060cd3a99a6637: a non-writable rises
attribute was defined for it.
Four, Reflect & Proxy
MDN:
Starting from ECMAScript 2015, JavaScript has gained support forProxy
andReflect
objects, allowing you to intercept and define custom behaviors for basic language operations (for example, attribute lookup, assignment, enumeration, function call, etc.). With these two objects, you can program at the JavaScript meta-level.
// Proxy的handler 和 Reflect 对象 13 个方法
.apply() // 对一个函数进行调用操作, 和 Function.prototype.apply() 功能类似
.construct() // 对构造函数进行 new 操作,相当于执行 new target(...args)
.get() // 获取对象身上某个属性的值,类似于 target[name]。
.has() // 判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同
.ownKeys() // 返回一个包含所有自身属性(不包含继承属性)的数组,类似于 Object.keys()
.set() // 将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true
.setPrototypeOf() // 设置对象原型的函数. 返回一个 Boolean, 如果更新成功,则返回true。
.defineProperty() // Object.defineProperty() 类似
.deleteProperty() // 作为函数的delete操作符,相当于执行 delete target[name]。
.getOwnPropertyDescriptor() //对象中存在该属性,则返回对应的属性描述符,类似于 Object.getOwnPropertyDescriptor()
.getPrototypeOf() // 类似于 Object.getPrototypeOf()。
.isExtensible() // 类似于 Object.isExtensible()
.preventExtensions() // 类似于 Object.preventExtensions()。返回一个Boolean。
1、Reflect
Reflect
is a built-in object that provides methods to intercept JavaScript operations.
The method is handler
160cd3a99a67ab 160cd3a99a67ac Proxy, but the Reflect
method is not a function object, so it cannot be constructed.
Reflect
all properties and methods are static (like Math
objects);
Take Reflect.has()
as an example, compare with in
operator to detect whether an object has a specific attribute:
Reflect.has(Object, "assign"); // true
"assign" in Object; // true
2、Proxy
Proxy
object introduced in ECMAScript 6 can intercept certain operations and implement custom behaviors.
For example, get the attributes on an object:
let handler = {
get: function(target, name){
return name in target ? target[name] : 42;
}};
let p = new Proxy({}, handler);
p.a = 1;
console.log(p.a, p.b); // 1, 42
Proxy
object defines a target (here an empty object) and a handler object get
The proxy object will not return undefined
when getting undefined attributes, but returns 42.
Five, generate code
The most common function 060cd3a99a6923 that uses meta-programming technology to generate code in eval()
incoming string as JavaScript code.
let str = "function sayHello(){console.log('hello')}";
eval(str);
sayHello();
// 输出
hello
Six, summary
Metaprogramming is programming when you turn the logic of a program to focus on itself (or its runtime environment), either to investigate its own structure or to modify it.
The main value of is that 160cd3a99a696c extends the ordinary mechanisms of the language to provide additional capabilities.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。