JAVASCRIPT中的元编程 (METAPROGRAMMING IN JAVASCRIPT)
As we learned from the earlier lesson, reflection represents introspection, intercession, and modification of the program. Prior to ES2015 (ES6), we had a few tools available to us to introspect and modify the behavior of the program such as Object.keys
or instanceof
operator among many.
正如我们从前面的课程中学到的, 反射表示对程序的自省 , 代祷和修改 。 在ES2015( ES6 )之前,我们可以使用一些工具来内省和修改程序的行为,例如Object.keys
或instanceof
运算符。
In ES2015, we received a Reflect
global object that provides some pretty useful methods for metaprogramming. Like Math
and JSON
objects, Reflect
is not a function nor it’s constructible. Its only job is to provide static methods for reflection. These methods can be divided into two categories.
在ES2015中,我们收到了Reflect
全局对象,该对象提供了一些非常有用的元编程方法 。 像Math
和JSON
对象一样, Reflect
不是函数也不是可构造的。 它唯一的工作是提供静态的反射方法。 这些方法可以分为两类。
Introspection methods are non-destructive methods. They are only used to introspect objects. Modification methods are destructive since they mutate the object or its behavior. Most of these methods are derived from old JavaScript implementations and we will talk about this as well.
自省方法是非破坏性方法。 它们仅用于自省对象。 修改方法具有破坏性,因为它们会改变对象或其行为。 这些方法大多数都来自旧JavaScript实现 ,我们也将对此进行讨论。
In the earlier lesson, we took a quick look at the Proxy
class which is used to intercept object operations. Proxy
handler methods and Reflect
static methods share the same function signature. We will talk more about this in the Proxy lesson (coming soon) but let’s discuss briefly why these method signatures are the same. For that, we need to look inside ECMAScript specifications.
在前面的课程中 ,我们快速了解了用于拦截对象操作的Proxy
类。 Proxy
处理程序方法和Reflect
静态方法共享相同的函数签名。 我们将在Proxy课程( 即将推出 )中详细讨论这一点,但让我们简要讨论一下为什么这些方法签名相同。 为此,我们需要查看ECMAScript规范。
对象内部方法和内部插槽 (Object Internal Methods and Internal Slots)
The 6.1.7.2 section of the ECMAScript 2015 specification talks about some weird internal properties and internal methods objects (descendants of Object
) can have. These properties or methods are implemented by the JavaScript engine but they are abstracted away from the runtime, hence you won’t be able to access them on the objects like normal properties.
ECMAScript 2015规范的6.1.7.2部分讨论了一些奇怪的内部属性和内部方法对象( Object
后代 )。 这些属性或方法是由JavaScript引擎实现的,但它们是从运行时中抽象出来的,因此您将无法像普通属性一样在对象上访问它们。
These are represented by the [[<name>]]
notation in the ECMAScript specification where name
is the name of the internal property or internal method. The internal property is called an internal slot and it contains a value associated with that object to represent some state of the object.
这些由ECMAScript规范中的[[<name>]]
表示法表示,其中name
是内部属性或内部方法的名称。 内部属性称为内部插槽 ,它包含与该对象关联的值,以表示该对象的某些状态 。
Let’s take a quick example. The [[GetPrototypeOf]]
internal method is implemented by all the objects and its job is to return the prototype of the object. When you execute Reflect.getPrototypeOf(obj)
method with obj
being the object whose prototype needs to be inspected, JavaScript engine calls the [[GetPrototypeOf]]
internal method of the obj
which returns the value of [[Prototype]]
internal slot of the object that contains the prototype.
让我们举个简单的例子。 [[GetPrototypeOf]]
内部方法由所有对象实现,其工作是返回对象的原型 。 当您以obj
作为需要检查其原型的对象执行Reflect.getPrototypeOf( obj )
方法时,JavaScript引擎将调用obj
的[[GetPrototypeOf]]
内部方法,该方法返回该obj
的[[Prototype]]
内部插槽的值包含原型的对象。
💡 The
obj.__proto__
also points to the prototype of theobj
and accessing it would be like accessing the[[Prototype]]
internal slot of theobj
.💡的
obj.__proto__
也指向的原型obj
和访问它会像访问[[Prototype]]
所述的内部插槽obj
。
When an internal method is invoked on an object such as obj
in the above example, it is called the “target” of the invocation. If the target doesn’t support an internal method, for example calling the Reflect.getPrototypeOf
on null
, a TypeError
exception is thrown.
在上面的示例中,当在诸如obj
的对象上调用内部方法时,该内部方法称为调用的“ 目标 ”。 如果目标不支持内部方法,例如在null
上调用Reflect.getPrototypeOf
,则抛出TypeError
异常。
Objects can have multiple internal slots and internal methods. ECMAScript specification does not describe how these internal methods are implemented but it describes the signature of the method call. The following are ES2015 internal methods implemented by all objects (hence essential). These internal methods may accept some arguments of specific ECMAScript language types and may return a value.
对象可以具有多个内部插槽和内部方法。 ECMAScript规范没有描述如何实现这些内部方法,而是描述了方法调用的签名。 以下是所有对象实现的ES2015内部方法( 因此必不可少 )。 这些内部方法可以接受某些特定ECMAScript语言类型的参数,并可以返回一个值。
Above are the ES2015 internal methods of a Function
object. Below are the internal slots of a property descriptor object that represents the state of an object’s property. If you want to know what a property descriptor is, I have written a separate lesson on this topic.
以上是Function
对象的ES2015内部方法。 以下是表示对象属性状态的属性描述符对象的内部插槽。 如果您想知道什么是属性描述符,我已经在此主题上写了另一节课 。
Internal slots and internal methods are the aid to the ECMAScript specification and they are referenced inside the specification to convey the appropriate behavior. For example, whenever [[Protoype]]
key appears, we know that specification is talking about the internal property that contains the prototype of the object.
内部插槽和内部方法是ECMAScript规范的帮助,在规范内部引用了它们以传达适当的行为。 例如,每当出现[[Protoype]]
键时,我们就知道规范正在谈论包含对象原型的内部属性。
Internal slots and internal methods help to achieve consistent behavior of the objects and an implementer (JavaScript engine) can correctly provide these implementations by looking at the specification. However, one doesn’t have to follow the exact signature as specified by the specification. This StackOverflow answer will guide you.
内部插槽和内部方法有助于实现对象的一致行为,并且实现者( JavaScript引擎 )可以通过查看规范正确地提供这些实现。 但是,不必遵循规范指定的确切签名。 这个 StackOverflow答案将指导您。
Every time you call Reflect
’s static method, some internal method is executed or some internal slot is accessed on the target
object which returns the result or changes the target
object’s behavior. Proxy
handler methods execute the same internal methods, hence method signature of the Proxy
handler methods and Reflect
’s static methods are the same.
每次调用Reflect
的静态方法时,都会在target
对象上执行某些内部方法或访问某些内部插槽,这将返回结果或更改target
对象的行为。 Proxy
处理程序方法执行相同的内部方法,因此Proxy
处理程序方法和Reflect
的静态方法的方法签名相同。
内省方法 (Introspection Methods)
These methods are purely used for introspection purpose and they do not modify the object, its behavior, or its internal state.
这些方法仅用于自省,它们不会修改对象,其行为或内部状态。
●Reflect.get (● Reflect.get)
Reflect.get(target, propertyKey[, receiver])
The Reflect.get
method when called with a target
and the propertyKey
returns the value of the propertyKey
property in the target
. The receiver
argument is used as this
if the property with the name propertyKey
is a getter function in the target
. If receiver
is missing, this
is target
.
所述Reflect.get
当与被叫方法target
和propertyKey
返回的值propertyKey
在属性target
。 所述receiver
参数被用作this
如果具有名称的属性propertyKey
是在吸气功能target
。 如果receiver
丢失, this
是target
。
The Reflect.get()
call resembles the target[propertyKey]
expression as it searches for the property value on the prototype of target
as well. If a property doesn’t exist on the target
, un