元编程
Metaprogramming is a programming technique in which computer programs have the ability to treat other programs as their data. It means that a program can be designed to read, generate, analyze or transform other programs, and even modify itself while running. In some cases, this allows programmers to minimize the number of lines of code to express a solution, in turn reducing development time. It also allows programs greater flexibility to efficiently handle new situations without recompilation.
——《Metaprogramming》
关于「元编程」的解释,维基百科上的定义略显晦涩,下面的知乎回答容易理解些:
怎样才算 meta-programming 呢?泛泛来说,只要是与编程相关的编程就算是 meta-programming 了——比如,若编程甲可以输出 A - Z,那么写程序甲算「编程」;而程序乙可以生成程序甲(也许还会连带着运行它输出 A - Z),那么编写程序乙的活动,就可以算作 meta-programming,「元编程」。
反射
在 ES2015 中添加的一些特性,让 JavaScript 能够更好地进行元编程:
- Symbols are all about Reflection within implementation - you sprinkle them on your existing classes and objects to change the behaviour.
- Reflect is all about Reflection through introspection - used to discover very low level information about your code.
- Proxy is all about Reflection through intercession - wrapping objects and intercepting their behaviours through traps.
Symbol
Reflect
在 ECMAScript 的「Table 5: Essential Internal Methods」和「Table 6: Additional Essential Internal Methods of Function Objects」中定义了一些「内部方法」,Reflect
对象的方法与其一一对应:
内部方法 | Reflect 对象的方法 |
说明 |
---|---|---|
[[GetPrototypeOf]] |
.getPrototypeOf() |
Determine the object that provides inherited properties for this object. A null value indicates that there are no inherited properties. |
[[SetPrototypeOf]] |
.setPrototypeOf() |
Associate this object with another object that provides inherited properties. Passing null indicates that there are no inherited properties. Returns true indicating that the operation was completed successfully or false indicating that the operation was not successful. |
[[IsExtensible]] |
.isExtensible() |
Determine whether it is permitted to add additional properties to this object. |
[[PreventExtensions]] |
.preventExtensions() |
Control whether new properties may be added to this object. Returns true if the operation was successful or false if the operation was unsuccessful. |
[[GetOwnProperty]] |
.getOwnPropertyDescriptor() |
Return a Property Descriptor for the own property of this object whose key is propertyKey, or undefined if no such property exists. |
[[DefineOwnProperty]] |
.defineProperty() |
Create or alter the own property, whose key is propertyKey, to have the state described by PropertyDescriptor. Return true if that property was successfully created/updated or false if the property could not be created or updated. |
[[HasProperty]] |
.has() |
Return a Boolean value indicating whether this object already has either an own or inherited property whose key is propertyKey. |
[[Get]] |
.get() |
Return the value of the property whose key is propertyKey from this object. If any ECMAScript code must be executed to retrieve the property value, Receiver is used as the this value when evaluating the code. |
[[Set]] |
.set() |
Set the value of the property whose key is propertyKey to value. If any ECMAScript code must be executed to set the property value, Receiver is used as the this value when evaluating the code. Returns true if the property value was set or false if it could not be set. |
[[Delete]] |
.deleteProperty() |
Remove the own property whose key is propertyKey from this object. Return false if the property was not deleted and is still present. Return true if the property was deleted or is not present. |
[[Enumerate]] |
.enumerate() |
Return an iterator object that produces the keys of the string-keyed enumerable properties of the object. |
[[OwnPropertyKeys]] |
.ownKeys() |
Return a List whose elements are all of the own property keys for the object. |
[[Call]] |
.apply() |
Executes code associated with this object. Invoked via a function call expression. The arguments to the internal method are a this value and a list containing the arguments passed to the function by a call expression. Objects that implement this internal method are callable. |
[[Construct]] |
.construct() |
Creates an object. Invoked via the new or super operators. The first argument to the internal method is a list containing the arguments of the operator. The second argument is the object to which the new operator was initially applied. Objects that implement this internal method are called constructors. A function object is not necessarily a constructor and such non-constructor function objects do not have a [[Construct]] internal method. |
其中 [[Enumerate]]
在 ES2016 中被废弃。