JavaScript元编程“反射” API简介

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.keysinstanceof运算符。

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全局对象,该对象提供了一些非常有用的元编程方法 。 像MathJSON对象一样, 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 [[]] 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是内部属性或内部方法的名称。 内部属性称为内部插槽 ,它包含与该对象关联的值,以表示该对象的某些状态

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 the obj and accessing it would be like accessing the [[Prototype]] internal slot of the obj.

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语言类型的参数,并可以返回一个值。

JavaScript元编程“反射” API简介_第1张图片
ECMAScript 2015 Table 5ECMAScript 2015表5
JavaScript元编程“反射” API简介_第2张图片
ECMAScript 2015 Table 6ECMAScript 2015表6

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内部方法。 以下是表示对象属性状态的属性描述符对象的内部插槽。 如果您想知道什么是属性描述符,我已经在此主题上写了另一节课

JavaScript元编程“反射” API简介_第3张图片
ECMAScript 2015 Table 4ECMAScript 2015表4

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当与被叫方法targetpropertyKey返回的值propertyKey在属性target 。 所述receiver参数被用作this如果具有名称的属性propertyKey是在吸气功能target 。 如果receiver丢失, thistarget

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, undefined is returned.

Reflect.get()调用也类似于target[propertyKey]表达式,因为它也在target原型上搜索属性值。 如果target上不存在属性,则返回undefined

JavaScript元编程“反射” API简介_第4张图片
reflect/get.jsreflect / get.js

You can also use Reflect.get on arrays (when target is an Array) using the propertyKey as the number or string index.

您还可以使用propertyKey作为numberstring索引,对数组(当targetArray )使用Reflect.get

This method internally calls the [[Get]] internal method of the object with propertyKey andreceiver on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法在内部使用propertyKey调用对象的[[Get]]内部方法,并在作为参数[ ref ]中receiver到的目标的target接收方。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.get( null, 'prop' )
Reflect.get( 'hello', 'length' )// TypeError: Reflect.get called on non-object

●Reflect.has (● Reflect.has)

Reflect.has(target, propertyKey)

The Reflect.has method checks for the existence of the propertyKey property on the target object or on its prototype. This works exactly like the in operator. If the property is found, it returns true, otherwise false is returned. This means a method name on an instance of a class would also return true (since it’s an inherited property).

Reflect.has方法检查target对象或其原​​型上是否存在propertyKey属性。 这与in运算符完全一样。 如果找到该属性,则返回true ,否则返回false 。 这意味着类实例上的方法名称也将返回true ( 因为它是继承的属性 )。

JavaScript元编程“反射” API简介_第5张图片
reflect/has.jsreflect / has.js

You can also use Reflect.has on arrays (when target is an Array) using the propertyKey as the number or string index.

also您也可以使用propertyKey作为numberstring索引在数组(当targetArray )上使用Reflect.has

This method internally calls the [[HasProperty]] internal method of the object with propertyKey on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法内部使用目标[[HasProperty]] propertyKey [[HasProperty]]调用对象的[[HasProperty]]内部方法,该目标是参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.has( null, 'prop' )
Reflect.has( 'hello', 'length' )// TypeError: Reflect.has called on non-object

If you want to check if an object has a property on itself and not on its prototype, then use the Object.hasOwnProperty method instead.

如果要检查对象是否具有属性而不是其原型,请使用该Object. hasOwnProperty Object. hasOwnProperty方法代替。

●Reflect.ownKeys (● Reflect.ownKeys)

Reflect.ownKeys(target)

The Reflect.ownKeys method returns an array containing the own properties of the target object. Unlike Object.keys, it includes non-enumerable properties as well. It also includes symbol properties as well. Therefore, the return value is equivalent to the result of Object.getOwnPropertyNames(target) and Object.getOwnPropertySymbols(target) combined.

Reflect.ownKeys方法返回一个包含target对象自身属性的数组。 与Object. keys不同Object. keys Object. keys ,它也包含不可枚举的属性。 它还包括符号属性。 因此,返回值等于Object. getOwnPropertyNames ( target )的结果Object. getOwnPropertyNames ( target ) Object. getOwnPropertyNames ( target )Object. getOwnPropertySymbols ( target ) Object. getOwnPropertySymbols ( target )组合在一起。

JavaScript元编程“反射” API简介_第6张图片
reflect/ownKeys.jsreflect / ownKeys.js

This method internally calls the [[OwnPropertyKeys]] internal method of the object on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法在内部调用目标上对象的[[OwnPropertyKeys]]内部方法,该目标是参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.ownKeys( null )
Reflect.ownKeys( 'hello' )// TypeError: Reflect.ownKeys called on non-object

●Reflect.getOwnPropertyDescriptor (● Reflect.getOwnPropertyDescriptor)

Reflect.getOwnPropertyDescriptor(target, propertyKey)

The Reflect.getOwnPropertyDescriptor method returns the property descriptor of the target object’s non-inherited property propertyKey. If the property doesn’t exist on the target, undefined is returned.

Reflect.getOwnPropertyDescriptor方法返回target对象的非继承属性propertyKey属性描述符 。 如果target上不存在该属性,则返回undefined

JavaScript元编程“反射” API简介_第7张图片
reflect/getOwnPropertyDescriptor.jsreflect / getOwnPropertyDescriptor.js

You can also use Reflect.getOwnPropertyDescriptor on arrays (when target is an Array) using the propertyKey as the number or string index.

also您还可以使用propertyKey作为numberstring索引在数组(当targetArray )上使用Reflect.getOwnPropertyDescriptor

This method internally calls the [[GetOwnProperty]] internal method of the object with propertyKey on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法在内部使用目标上的propertyKey调用对象的[[GetOwnProperty]]内部方法,该目标是参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.getOwnPropertyDescriptor( null, 'prop' )
Reflect.getOwnPropertyDescriptor( 'hello', 'length' )// TypeError: Reflect.getOwnPropertyDescriptor called on non-object

We also have a similar Object.getOwnPropertyDescriptor method that returns the property descriptor of the target but in that case, if the target isn’t an object, it will be coerced into an object (in ES2015) using its constructor (such as "hey" into String("hey")) except null and undefined values (since they do not have a public constructor).

我们也有一个类似的Object. getOwnPropertyDescriptor Object. getOwnPropertyDescriptor方法,该方法返回target的属性描述符,但在这种情况下,如果target不是对象,则将使用其构造函数将其强制为对象( 在ES2015中 )( 例如, "hey" Hey "hey" 转换为 String("hey") ),但nullundefined值除外( 因为它们没有公共构造函数 )。

Object.getOwnPropertyDescriptor( null )// TypeError: Cannot convert undefined or null to objectObject.getOwnPropertyDescriptor( 'hello', 'length' )// {value: 5, writable: false, enumerable: false, …}Object.getOwnPropertyDescriptor( {}, 'prop' )// undefined

●Reflect.getPrototypeOf (● Reflect.getPrototypeOf)

Reflect.getPrototypeOf(target)

The Reflect.getPrototypeOf method returns the prototype of the target object. If target doesn’t have a prototype, null is returned.

Reflect.getPrototypeOf方法返回target对象的原型。 如果target没有原型,则返回null

JavaScript元编程“反射” API简介_第8张图片
reflect/getPrototypeOf.jsreflect / getPrototypeOf.js

This method internally calls the [[GetPrototypeOf]] internal method of the object on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法在内部调用目标上对象的[[GetPrototypeOf]]内部方法,该目标是参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.getPrototypeOf( null )
Reflect.getPrototypeOf( 'hello' )// TypeError: Reflect.getPrototypeOf called on non-object

We also have a similar Object.getPrototypeOf method that returns the prototype of the target but in this case, if the target isn’t an object, it will be coerced into an object (in ES2015) using its constructor except null and undefined values (since they do not have a public constructor).

我们也有一个类似的Object. getPrototypeOf Object. getPrototypeOf方法,该方法返回target的原型,但在这种情况下,如果target不是对象,则将使用其构造函数将其强制为对象( 在ES2015中 ),但nullundefined值除外( 因为它们没有公共的)构造函数 )。

Object.getPrototypeOf( null )// TypeError: Cannot convert undefined or null to objectObject.getPrototypeOf( 'hello' )// String {constructor: String(), anchor: ƒ, big: ƒ, …}Object.getPrototypeOf( {} )// Object {constructor: Object(), __defineGetter__: ƒ, …}

●Reflect.isExtensible (● Reflect.isExtensible)

Reflect.isExtensible(target)

The Reflect.isExtensible method is used to check if the target object is extensible. If the target is extensible, meaning if new properties can be added to it, this method returns true, otherwise false is returned.

Reflect.isExtensible方法用于检查target对象是否可扩展 。 如果target是可扩展的,这意味着如果可以向其添加新属性,则此方法返回true ,否则返回false

JavaScript元编程“反射” API简介_第9张图片
reflect/isExtensible.jsreflect / isExtensible.js

The Object.preventExtenstions() method prevents you from adding any new properties to the object, however, you are allowed to perform any other operations on the object. The Object.freeze() and Object.seal() methods also make the object non-extensible.

Object. preventExtenstions () Object. preventExtenstions ()方法可防止您向该对象添加任何新属性,但是,允许您对该对象执行任何其他操作。 Object. freeze () Object. freeze ()Object. seal () Object. seal ()方法还使对象不可扩展。

This method internally calls the [[IsExtensible]] internal method of the object on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法在内部调用目标上对象的[[IsExtensible]]内部方法,该目标是在参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.isExtensible( null )
Reflect.isExtensible( 'hello' )// TypeError: Reflect.isExtensible called on non-object

We also have a similar Object.isExtensible method that returns the prototype of the target but in this case, if the target isn’t an object, false is returned instead of throwing a TypeError.

我们也有一个类似的Object. isExtensible Object. isExtensible方法,该方法返回target的原型,但在这种情况下,如果target不是对象,则返回false而不是抛出TypeError

Object.isExtensible( null )// falseObject.isExtensible( 'hello' )// falseObject.isExtensible( {} )// true

I know you would say, leave Reflect.isExtensible, I will use the Object.isExtensible method as it doesn’t throw an error. Well, that’s the part of a bigger problem as you would then need to type check incoming target value to make sure whether the false was returned because the target is not extensible or because it is a primitive value.

我知道您会说,离开Reflect.isExtensible ,我将使用Object.isExtensible方法,因为它不会引发错误。 好吧,这是一个更大问题的一部分,因为您随后需要键入检查传入的target以确保是否由于target不可扩展或因为它是原始值而返回了false

修改方法 (Modification Methods)

These methods modify the target value or its behavior, or its internal state.

这些方法修改target或其行为或内部状态。

●Reflect.deleteProperty (● Reflect.deleteProperty)

Reflect.deleteProperty(target, propertyKey)

The Reflect.deleteProperty method deletes the property propertyKey from the target object. It returns true if the property was successfully deleted from the target, else false is returned. It’s equivalent of using delete operator.

Reflect.deleteProperty方法从target对象中删除属性propertyKey 。 如果该属性已成功从target删除,则返回true ,否则返回false 。 等效于使用delete运算符。

Like delete operator, if the property propertyKey doesn’t exist, it will always return true. This method will not delete the property on target’s prototype chain, only own properties can be deleted. Also, non-configurable properties can not be deleted.

delete运算符一样,如果属性propertyKey不存在,它将始终返回true 。 此方法不会删除target原型链上的属性,只能删除自己的属性。 同样,无法删除不可配置的属性。

JavaScript元编程“反射” API简介_第10张图片
reflect/deleteProperty.jsreflect / deleteProperty.js

You can also use Reflect.deleteProperty on arrays (when target is an Array) using the propertyKey as the number or string index.

also您还可以使用propertyKey作为numberstring索引在数组(当targetArray )上使用Reflect.deleteProperty

This method internally calls the [[Delete]] internal method of the object with the propertyKey on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法内部使用目标上的propertyKey调用对象的[[Delete]]内部方法,该目标是在参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.deleteProperty( null, 'prop' )
Reflect.deleteProperty( 'hello', 'length' )// TypeError: Reflect.deleteProperty called on non-object

●Reflect.set (● Reflect.set)

Reflect.set(target, propertyKey, value[, receiver])

The Reflect.set works like Reflect.get but instead of retrieving the value of target’s propertyKey property, it updates the target’s own property value with the value received in the argument. If a property with the name propertyKey already exists, its value will be updated else a new property will be created.

Reflect.set工作方式与Reflect.get但是它不检索targetpropertyKey属性的值,而是使用value接收的value更新target自身的属性值。 如果名称propertyKey已经存在,则其值将被更新,否则将创建一个新的属性。

If the property already exists and it has a setter function, the this value inside the setter function will be the receiver if provided, else target will be used. This method is equivalent to using the target[propertyKey] = value expression.

如果属性已经存在并且具有设置器功能,则设置器功能内的this值将是receiver如果提供),否则将使用target 。 此方法等效于使用target[ propertyKey ] = value表达式。

JavaScript元编程“反射” API简介_第11张图片
reflect/set.jsreflect / set.js

You can also use Reflect.set on arrays (when target is an Array) using the propertyKey as the number or string index.

also您还可以使用propertyKey作为numberstring索引在数组(当targetArray )上使用Reflect.set

This method internally calls the [[Set]] internal method of the object with the propertyKey, value and receiver on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法内部使用目标的propertyKeyvaluereceiver内部调用对象的[[Set]]内部方法,该目标是在参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.set( null, 'prop', 'val' )
Reflect.set( 'hello', 'length', 2 )// TypeError: Reflect.set called on non-object

●Reflect.defineProperty (● Reflect.defineProperty)

Reflect.defineProperty(target, propertyKey, descriptor)

The Reflect.defineProperty creates a new property on the target object with propertyKey name and descriptor which is the property descriptor.

Reflect.definePropertytarget对象上创建一个新属性,该属性具有propertyKey名称和descriptor ,该描述descriptor是属性描述符。

If the property already exists, only the property descriptor will be updated. If only some property descriptor fields are provided in the descriptor, only those fields will be updated. If the property was successfully set, this method returns true, else false is returned.

如果属性已经存在,则仅属性描述符将被更新。 如果只提供一些属性描述符字段descriptor ,只有那些字段将被更新。 如果成功设置了属性,则此方法返回true ,否则返回false

JavaScript元编程“反射” API简介_第12张图片
reflect/defineProperty.jsreflect / defineProperty.js

You can also use Reflect.defineProperty on arrays (when target is an Array) using the propertyKey as the number or string index.

also您还可以使用propertyKey作为numberstring索引在数组(当targetArray )上使用Reflect.defineProperty

This method internally calls the [[DefineOwnProperty]] internal method of the object with the propertyKey and descriptor on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法在内部调用对象的[[DefineOwnProperty]]内部方法,该对象的内部具有propertyKeydescriptor ,该对象是在参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.defineProperty( null, 'prop', {value: 2})
Reflect.defineProperty( 'hello', 'length', {value: 3})// TypeError: Reflect.defineProperty called on non-object

We also have a similar Object.defineProperty method that does exactly the same thing. But this method returns the updated target object back instead of returning a boolean value. Also, if the property could not be defined on the target, it throws the TypeError exception instead of returning false.

我们也有一个类似的Object. defineProperty 完全一样的Object. defineProperty方法。 但是此方法返回更新后的target对象,而不是返回boolean值。 另外,如果无法在target上定义该属性,则它将抛出TypeError异常,而不是返回false

●Reflect.preventExtensions (● Reflect.preventExtensions)

Reflect.preventExtensions(target)

The Reflect.preventExtensions method makes the target object non-extensible. Once an object is non-extensible, no new properties can be added to the object. This method returns true if the object was made non-extensible, else false is returned.

Reflect.preventExtensions方法使target对象不可扩展。 一旦对象不可扩展,就无法将新属性添加到该对象。 如果将对象设为不可扩展,则此方法返回true ,否则返回false

JavaScript元编程“反射” API简介_第13张图片
reflect/preventExtensions.jsreflect / preventExtensions.js

This method internally calls the [[PreventExtensions]] internal method of the object on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法在内部调用目标上对象的[[PreventExtensions]]内部方法,该目标是参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.preventExtensions( null )
Reflect.preventExtensions( 'hello' )// TypeError: Reflect.preventExtensions called on non-object

We also have a similar Object.preventExtensions method that does exactly the same thing. But this method returns the updated target object back instead of returning a boolean value. If the target is not an object, the original value is returned back.

我们也有一个类似的Object. preventExtensions 完全一样的Object. preventExtensions方法。 但是此方法返回更新后的target对象,而不是返回boolean值。 如果target不是对象,则返回原始值。

Object.preventExtensions( null )// falseObject.preventExtensions( 'hello' )// 'hello'Object.preventExtensions( {name: 'ross'} )// {name: 'ross'}

●Reflect.setPrototypeOf (● Reflect.setPrototypeOf)

Reflect.setPrototypeOf(target, prototype)

The Reflect.setPrototypeOf method sets the prototype prototype on the target object. If the prototype was successfully set on the target, it returns true, else false is returned. If target is non-extensible, the prototype won’t be set and false would be returned.

Reflect.setPrototypeOf方法在target对象上设置prototype原型。 如果原型已成功设置在target ,则返回true ,否则返回false 。 如果target是不可扩展的,则不会设置原型,并且将返回false

var obj = Object.preventExtensions({});
Reflect.setPrototypeOf(obj, null);// false

If prototype is not a valid Object or null, then a TypeError is thrown.

如果prototype不是有效的Objectnull ,则TypeError

Reflect.setPrototypeOf({}, "")
Reflect.setPrototypeOf(function(){}, "")// TypeError: Object prototype may only be an Object or null
JavaScript元编程“反射” API简介_第14张图片
reflect/setPrototypeOf.jsreflect / setPrototypeOf.js

This method internally calls the [[SetPrototypeOf]] internal method of the object with prototype on the target which is the target received in the arguments [ref]. Therefore, if a non-object target (primitive value) is provided, this method call will throw a TypeError exception.

此方法在内部调用对象的[[SetPrototypeOf]]内部方法,该对象的prototype为目标,该target为参数[ ref ]中接收的target 。 因此,如果提供了非对象target ( 原始值 ),则此方法调用将引发TypeError异常。

Reflect.setPrototypeOf( null, null )
Reflect.setPrototypeOf( 'hello', null )// TypeError: Reflect.setPrototypeOf called on non-object

We also have a similar Object.setPrototypeOf method that does exactly the same thing. But this method returns the updated target object back instead of returning a boolean value. If the target is not an Object or null or if the target is non-extensible, a TypeError is thrown.

我们也有一个类似的Object. setPrototypeOf Object. setPrototypeOf方法执行完全相同的操作。 但是此方法返回更新后的target对象,而不是返回boolean值。 如果target不是Objectnull或者target是不可扩展的,则抛出TypeError

Object.setPrototypeOf( null, null )// TypeError: Object.setPrototypeOf called on null or undefinedObject.setPrototypeOf( Object.preventExtensions({}), null )// TypeError: # is not extensibleObject.setPrototypeOf( {name: 'ross'}, "")// TypeError: Object prototype may only be an Object or nullObject.setPrototypeOf( {name: 'ross'}, null )// {name: 'ross'} 
      

●Reflect.apply (● Reflect.apply)

Reflect.apply(target, thisArgument, argumentsList)

The Reflect.apply isn’t exactly a modification method. This method calls a function which is the target with the argumentsList arguments array and provides thisArgument as the this value for the function call.

Reflect.apply并非完全是一种修改方法。 该方法使用argumentsList arguments数组thisArgument作为target的函数,并提供thisArgument作为函数调用的this值。

This is equivalent to calling apply prototype method of the target (if the target is a function) but with some caveats. If the argumentsList is null or undefined, Reflect.apply would throw a TypeError while apply prototype method would call the function without any arguments.

这等效于调用target apply原型方法( 如果 target 是一个函数 ),但有一些警告。 如果argumentsListnullundefinedReflect.apply会抛出一个TypeError ,而apply原型法会调用该函数不带任何参数。

let func = ( ...args ) => console.log(args);func.apply(null, undefined)func.apply(null, null)func.apply(null, {})// []func.apply(null, "")// TypeError: CreateListFromArrayLike called on non-objectfunc.apply(null, [1, 2, 3])// [1, 2, 3]Reflect.apply(func, null, undefined)
Reflect.apply(func, null, null)
Reflect.apply(func, null, "")// TypeError: CreateListFromArrayLike called on non-objectReflect.apply(func, null, {})// []▶ Reflect.apply(func, null, [1, 2, 3])// [1, 2, 3]

This method internally calls the [[Call]] internal method of the function with thisArgument and argumentsList on the target which is the target received in the arguments [ref]. Therefore, if a non-function target is provided, this method call will throw a TypeError exception.

此方法内部使用目标上的thisArgumentargumentsList函数的[[Call]]内部方法,该目标是在参数[ ref ]中接收的target 。 因此,如果提供了非功能target ,则此方法调用将引发TypeError异常。

Reflect.apply( null, null, [] )// TypeError: Function.prototype.apply was called on null, which is a object and not a functionReflect.apply( 'hello', null, [] )// TypeError: Function.prototype.apply was called on hello, which is a string and not a functionReflect.apply( {}, null, [] )// TypeError: Function.prototype.apply was called on #, which is a object and not a function 
      

●Reflect.construct (● Reflect.construct)

Reflect.construct(target, argumentsList[, newTarget])

The Reflect.construct method constructs an object from the target constructor function (class). This is equivalent to using the new operator with argumentsList such as new target(...argumentsList).

Reflect.construct方法从target构造函数( class )构造一个对象。 这等效于将new运算符与argumentsList一起使用,例如new target(... argumentsList )

The newTarget is also a constructor function whose prototype would be the prototype of the newly created instance but it would be created using the target’s constructor function as shown below.

newTarget也是一个构造函数,其prototype将是新创建的实例的原型,但是它将使用target的构造函数创建,如下所示。

let instance = Object.create( newTarget.prototype )target.apply( instance, argumentsList );

If the newTarget is not provided, newTarget would the target which means the above scenario would like something like this.

如果newTarget没有提供, newTarget会的target ,这意味着上述情况下想这样的事情。

let instance = Object.create( target.prototype )target.apply( instance, argumentsList );
JavaScript元编程“反射” API简介_第15张图片
reflect/construct.jsreflect / construct.js

This method internally calls the [[Construct]] internal method of the function with argumentsList and newTarget, on the target which is the target received in the arguments [ref].

该方法内部调用[[ Construct ]]与该功能的内部方法argumentsListnewTarget ,在其上是目标target中的参数收到的[ 参考文献 ]。

Therefore, if a non-function or non-constructible target is provided, this method call will throw a TypeError exception. Similarly, if the newTarget isn’t a function (or a class) with a prototype, a TypeError is thrown.

因此,如果提供了非功能或不可构造的target ,则此方法调用将引发TypeError异常。 同样,如果newTarget不是带有原型的函数( 或类 ),则抛出TypeError

Reflect.construct( {}, [] )// TypeError: # is not a constructorReflect.construct( Symbol, [] )// TypeError: Symbol is not a constructorReflect.construct( null, [] )// TypeError: null is not a constructorReflect.construct( Object, [], Symbol )// Symbol {}Reflect.construct( Object, [], Reflect )
Reflect.construct( Object, [], Math )
Reflect.construct( Object, [], JSON )// TypeError: # is not a constructor

The Reflect.enumerate method was removed in ECMAScript 2016 and it is obsolete (source). With this, the [[Enumerate]] internal method was also removed. Therefore, Proxy.enumerate handler method was also removed (source).

Reflect.enumerate方法已在ECMAScript 2016中删除,并且已过时( )。 这样, [[Enumerate]]内部方法也被删除。 因此,还删除了Proxy.enumerate处理程序方法( )。

Though most of the Reflect methods do pretty much the same thing as some operators, some static methods of the Object and some prototype methods of the Function do as we have seen. However, the main agenda behind the inception of Reflect was to bring a unified API for reflection.

尽管大多数Reflect方法与某些operators几乎具有相同的Function但正如我们所见, Object某些静态方法和Function一些原型方法都可以完成。 但是, Reflect诞生之后的主要议程是带来一个统一的API进行反射

Everything can be done through method calls now such as creating an instance or getting, setting, and deleting object properties. As the language grows, more and more methods would be added to simplify complicated things.

现在可以通过方法调用来完成所有操作,例如创建实例或获取,设置和删除对象属性。 随着语言的增长,将添加越来越多的方法来简化复杂的事情。

Reflect is a powerful tool when combined with Proxy which we will see in the next lesson.

Proxy结合使用时, Reflect是一个功能强大的工具,我们将在下一课中看到它。

Image for post
Support Me on Patreon在Patreon上支持我 / / GitHubGitHub TwitterTwitter StackOverflowStackOverflow InstagramInstagram

翻译自: https://medium.com/jspoint/introduction-to-reflect-api-for-metaprogramming-in-javascript-8b5a2bb84282

你可能感兴趣的:(python,javascript,ViewUI)