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 [[
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 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语言类型的参数,并可以返回一个值。
ECMAScript 2015 Table 5ECMAScript 2015表5 ECMAScript 2015 Table 6ECMAScript 2015表6Above 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
, undefined
is returned.
Reflect.get()
调用也类似于target[propertyKey]
表达式,因为它也在target
原型上搜索属性值。 如果target
上不存在属性,则返回undefined
。
You can also use
Reflect.get
on arrays (whentarget
is anArray
) using thepropertyKey
as thenumber
orstring
index.您还可以使用
propertyKey
作为number
或string
索引,对数组(当target
是Array
)使用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
( 因为它是继承的属性 )。
You can also use
Reflect.has
on arrays (whentarget
is anArray
) using thepropertyKey
as thenumber
orstring
index.also您也可以使用
propertyKey
作为number
或string
索引在数组(当target
是Array
)上使用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 )
组合在一起。
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
。
You can also use
Reflect.getOwnPropertyDescriptor
on arrays (whentarget
is anArray
) using thepropertyKey
as thenumber
orstring
index.also您还可以使用
propertyKey
作为number
或string
索引在数组(当target
是Array
)上使用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")
),但null
和undefined
值除外( 因为它们没有公共构造函数 )。
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
。
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中 ),但null
和undefined
值除外( 因为它们没有公共的)构造函数 )。
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
。
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
原型链上的属性,只能删除自己的属性。 同样,无法删除不可配置的属性。
You can also use
Reflect.deleteProperty
on arrays (whentarget
is anArray
) using thepropertyKey
as thenumber
orstring
index.also您还可以使用
propertyKey
作为number
或string
索引在数组(当target
是Array
)上使用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
但是它不检索target
的propertyKey
属性的值,而是使用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
表达式。
You can also use
Reflect.set
on arrays (whentarget
is anArray
) using thepropertyKey
as thenumber
orstring
index.also您还可以使用
propertyKey
作为number
或string
索引在数组(当target
是Array
)上使用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.
此方法内部使用目标的propertyKey
, value
和receiver
内部调用对象的[[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.defineProperty
在target
对象上创建一个新属性,该属性具有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
。
You can also use
Reflect.defineProperty
on arrays (whentarget
is anArray
) using thepropertyKey
as thenumber
orstring
index.also您还可以使用
propertyKey
作为number
或string
索引在数组(当target
是Array
)上使用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]]
内部方法,该对象的内部具有propertyKey
和descriptor
,该对象是在参数[ 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
。
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
不是有效的Object
或null
,则TypeError
。
Reflect.setPrototypeOf({}, "")
Reflect.setPrototypeOf(function(){}, "")// TypeError: Object prototype may only be an Object or null
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
不是Object
或null
或者target
是不可扩展的,则抛出TypeError
。
Object.setPrototypeOf( null, null )// TypeError: Object.setPrototypeOf called on null or undefinedObject.setPrototypeOf( Object.preventExtensions({}), null )// ❌ TypeError: #Object.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
是一个函数 ),但有一些警告。 如果argumentsList
为null
或undefined
, Reflect.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-object▶ func.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.
此方法内部使用目标上的thisArgument
和argumentsList
函数的[[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 #
●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 );
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 ]]
与该功能的内部方法argumentsList
和newTarget
,在其上是目标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: #Reflect.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: #
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
是一个功能强大的工具,我们将在下一课中看到它。
翻译自: https://medium.com/jspoint/introduction-to-reflect-api-for-metaprogramming-in-javascript-8b5a2bb84282