【易客吧】_全网激活码总代_激活码商城

您现在的位置是:首页 > 热门资讯 > 正文

热门资讯

ES6 Reflect:深入理解对象的反射操作 (es6reflect有什么用)

用户投稿2024-04-16热门资讯27

引言

ES6 中引入了 Reflect 对象,它提供了一系列操作来反射 JavaScript 对象。反射操作允许我们以一种内省的方式来访问和修改对象的行为,从而增强了 JavaScript 的灵活性。

Reflect 对象

Reflect 对象是一个全局对象,它包含了一组静态方法来操作对象。这些方法提供了与对象属性和方法的交互,以及对对象行为的控制。

Reflect.get() 和 Reflect.set()

`Reflect.get()` 方法用于获取对象的属性值。它接受三个参数:target: 要获取属性值的对象propertyKey: 要获取的属性的名称或符号receiver(可选): 如果 `target` 是一个 Proxied 对象,则指定接收操作的对象`Reflect.set()` 方法用于设置对象的属性值。它接受四个参数:target: 要设置属性值的对象propertyKey: 要设置的属性的名称或符号value: 要设置的值receiver(可选): 如果 `target` 是一个 Proxied 对象,则指定接收操作的对象

Reflect.has() 和 Reflect.deleteProperty()

`Reflect.has()` 方法用于检查对象是否具有指定的属性。它接受两个参数:target: 要检查的对象propertyKey: 要检查的属性的名称或符号`Reflect.deleteProperty()` 方法用于删除对象的属性。它接受两个参数:target: 要删除属性的对象propertyKey: 要删除的属性的名称或符号

Reflect.apply(), Reflect.construct() 和 Reflect.defineProperty()

`Reflect.apply()` 方法用于调用一个函数,并以给定参数和 `this` 值的上下文调用它。它接受三个参数:target: 要调用的函数thisArg: 指定 `this` 值的对象args: 要传递给函数的 arguments 对象`Reflect.construct()` 方法用于创建一个新对象的实例,并以给定参数的上下文调用它的构造函数。它接受三个参数:target: 构造函数args: 要传递给构造函数的 arguments 对象newTarget(可选): 新对象的构造函数`Reflect.defineProperty()` 方法用于在对象上定义一个新属性或修改现有属性。它接受三个参数:target: 要定义属性的对象propertyKey: 属性的名称或符号attributes: 属性的属性描述符

Reflect.ownKeys()

`Reflect.ownKeys()` 方法返回一个包含对象自身属性名称或符号的数组。它接受一个参数:target: 要获取属性的数组的对象

Reflect.preventExtensions()、Reflect.isExtensible() 和 Reflect.getPrototypeOf()

`Reflect.preventExtensions()` 方法用于防止对象被扩展(添加新属性)。它接受一个参数:target: 要防止扩展的对象`Reflect.isExtensible()` 方法返回一个布尔值,表示对象是否可以被扩展。它接受一个参数:target: 要检查的可扩展性的对象`Reflect.getPrototypeOf()` 方法返回对象的原型对象。它接受一个参数:target: 要获取原型的对象

Reflect.setPrototypeOf()

`Reflect.setPrototypeOf()` 方法用于设置对象的原型对象。它接受两个参数:target: 要设置原型的对象prototype: 要设置的原型对象

Reflect 在 Proxy 中的使用

Reflect 对象在 Proxy(代理)中扮演着重要的角色。Proxy 是 ES6 中引入的一种对象包装器,允许我们拦截和修改对象的默认行为。在 Proxy 的 `handler` 对象中,我们可以使用 Reflect 方法来访问和修改被代理的对象。这使得我们可以实现自定义的行为,如属性验证、数据校验和拦截。

使用 Reflect 的优点

使用 Reflect 对象提供了以下优点:统一的接口: `Reflect` 为对象操作提供了一个统一的接口,简化了与对象的交互。更好的性能: `Reflect` 方法在速度上往往比传统的对象操作方法更有效率。更具可扩展性: `Reflect` 允许我们创建自定义的行为,这增强了 JavaScript 的灵活性。针对 Proxy 的支持: `Reflect` 在 Proxy 中扮演着关键角色,允许我们实现高级的对象代理场景。

结论

ES6 中的 Reflect 对象提供了强大的方法来反射 JavaScript 对象。它允许我们深入访问和修改对象的行为,从而增强了 JavaScript 的灵活性、性能和可扩展性。特别是,在 Proxy 中使用 Reflect 允许我们实现自定义的行为并拦截对象的默认操作。 ES6 Reflect:深入理解对象的反射操作 (es6reflect有什么用) 第1张

JAVA中的反射和反射机制到底是什么啊?

Java Reflection (JAVA反射) 详解Java语言反射提供一种动态链接程序组件的多功能方法。 它允许程序创建和控制任何类的对象(根据安全性限制),无需提前硬编码目标类。 这些特性使得反射特别适用于创建以非常普通的方式与对象协作的库。 例如,反射经常在持续存储对象为数据库、XML或其它外部格式的框架中使用。 Java reflection 非常有用,它使类和数据结构能按名称动态检索相关信息,并允许在运行着的程序中操作这些信息。 Java 的这一特性非常强大,并且是其它一些常用语言,如 C、C++、Fortran 或者 Pascal 等都不具备的。 但反射有两个缺点。 第一个是性能问题。 用于字段和方法接入时反射要远慢于直接代码。 性能问题的程度取决于程序中是如何使用反射的。 如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。 即使测试中最坏情况下的计时图显示的反射操作只耗用几微秒。 仅反射在性能关键的应用的核心逻辑中使用时性能问题才变得至关重要。 许多应用中更严重的一个缺点是使用反射会模糊程序内部实际要发生的事情。 程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问题。 反射代码比相应的直接代码更复杂,正如性能比较的代码实例中看到的一样。 解决这些问题的最佳方案是保守地使用反射——仅在它可以真正增加灵活性的地方——记录其在目标类中的使用。 Reflection是Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说自审,并能直接操作程序的内部属性。 例如,使用它能获得 Java 类中各成员的名称并显示出来。 Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。 例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。 JavaBean 是 reflection 的实际应用之一,它能让一些工具可视化的操作软件组件。 这些工具通过 reflection 动态的载入并取得 Java 组件(类) 的属性。 1. 一个简单的例子考虑下面这个简单的例子,让我们看看 reflection 是如何工作的。 import .*;public class DumpMethods {public static void main(String args[]) {try {Class c = (args[0]);Method m[] = ();for (int i = 0; i < ; i++)(m[i]());} catch (Throwable e) {(e);}}}按如下语句执行:java DumpMethods 它的结果输出为:public ()public synchronized ()public synchronized ()public boolean ()public synchronized int ()这样就列出了 类的各方法名以及它们的限制符和返回类型。 这个程序使用 载入指定的类,然后调用 getDeclaredMethods 来获取这个类中定义了的方法列表。 是用来描述某个类中单个方法的一个类。 2.开始使用 Reflection用于 reflection 的类,如 Method,可以在 包中找到。 使用这些类的时候必须要遵循三个步骤:第一步是获得你想操作的类的 对象。 在运行中的 Java 程序中,用 类来描述类和接口等。 下面就是获得一个 Class 对象的方法之一:Class c = ();这条语句得到一个 String 类的类对象。 还有另一种方法,如下面的语句:Class c = ;或者Class c = ;它们可获得基本类型的类信息。 其中后一种方法中访问的是基本类型的封装类 (如 Integer) 中预先定义好的 TYPE 字段。 第二步是调用诸如 getDeclaredMethods 的方法,以取得该类中定义的所有方法的列表。 一旦取得这个信息,就可以进行第三步了——使用 reflection API 来操作这些信息,如下面这段代码:Class c = ();Method m[] = ();(m[0]());它将以文本方式打印出 String 中定义的第一个方法的原型。 在下面的例子中,这三个步骤将为使用 reflection 处理特殊应用程序提供例证。 模拟 instanceof 操作符得到类信息之后,通常下一个步骤就是解决关于 Class 对象的一些基本的问题。 例如, 方法可以用于模拟 instanceof 操作符:class A {}public class instance1 {public static void main(String args[]) {try {Class cls = (A);boolean b1 = (new Integer(37));(b1);boolean b2 = (new A());(b2);} catch (Throwable e) {(e);}}}在这个例子中创建了一个 A 类的 Class 对象,然后检查一些对象是否是 A 的实例。 Integer(37) 不是,但 new A()是。 3.找出类的方法找出一个类中定义了些什么方法,这是一个非常有价值也非常基础的 reflection 用法。 下面的代码就实现了这一用法:import .*;public class method1 {private int f1(Object p, int x) throws NullPointerException {if (p == null)throw new NullPointerException();return x;}public static void main(String args[]) {try {Class cls = (method1);Method methlist[] = ();for (int i = 0; i < ; i++) {Method m = methlist[i];(name = + ());(decl class = + ());Class pvec[] = ();for (int j = 0; j < ; j++)(param # + j + + pvec[j]);Class evec[] = ();for (int j = 0; j < ; j++)(exc # + j + + evec[j]);(return type = + ());(-----);}} catch (Throwable e) {(e);}}}这个程序首先取得 method1 类的描述,然后调用 getDeclaredMethods 来获取一系列的 Method 对象,它们分别描述了定义在类中的每一个方法,包括 public 方法、protected 方法、package 方法和 private 方法等。 如果你在程序中使用 getMethods 来代替 getDeclaredMethods,你还能获得继承来的各个方法的信息。 取得了 Method 对象列表之后,要显示这些方法的参数类型、异常类型和返回值类型等就不难了。 这些类型是基本类型还是类类型,都可以由描述类的对象按顺序给出。 输出的结果如下:name = f1decl class = class method1param #0 class #1 intexc #0 class type = int-----name = maindecl class = class method1param #0 class [;return type = void4.获取构造器信息获取类构造器的用法与上述获取方法的用法类似,如:import .*;public class constructor1 {public constructor1() {}protected constructor1(int i, double d) {}public static void main(String args[]) {try {Class cls = (constructor1);Constructor ctorlist[] = ();for (int i = 0; i < ; i++) {Constructor ct = ctorlist[i];(name = + ());(decl class = + ());Class pvec[] = ();for (int j = 0; j < ; j++)(param # + j + + pvec[j]);Class evec[] = ();for (int j = 0; j < ; j++)(exc # + j + + evec[j]);(-----);}} catch (Throwable e) {(e);}}}这个例子中没能获得返回类型的相关信息,那是因为构造器没有返回类型。 这个程序运行的结果是:name = constructor1decl class = class constructor1-----name = constructor1decl class = class constructor1param #0 intparam #1 double5.获取类的字段(域) 找出一个类中定义了哪些数据字段也是可能的,下面的代码就在干这个事情:import .*;public class field1 {private double d;public static final int i = 37;String s = testing;public static void main(String args[]) {try {Class cls = (field1);Field fieldlist[] = ();for (int i = 0; i < ; i++) {Field fld = fieldlist[i];(name = + ());(decl class = + ());(type = + ());int mod = ();(modifiers = + (mod));(-----);}} catch (Throwable e) {(e);}}}这个例子和前面那个例子非常相似。 例中使用了一个新东西 Modifier,它也是一个 reflection 类,用来描述字段成员的修饰语,如“private int”。 这些修饰语自身由整数描述,而且使用 来返回以“官方”顺序排列的字符串描述 (如“static”在“final”之前)。 这个程序的输出是:name = ddecl class = class field1type = doublemodifiers = private-----name = idecl class = class field1type = intmodifiers = public static final-----name = sdecl class = class field1type = class =和获取方法的情况一下,获取字段的时候也可以只取得在当前类中申明了的字段信息 (getDeclaredFields),或者也可以取得父类中定义的字段 (getFields) 。 6.根据方法的名称来执行方法文本到这里,所举的例子无一例外都与如何获取类的信息有关。 我们也可以用 reflection 来做一些其它的事情,比如执行一个指定了名称的方法。 下面的示例展示了这一操作:import .*;public class method2 {public int add(int a, int b) {return a + b;}public static void main(String args[]) {try {Class cls = (method2);Class partypes[] = new Class[2];partypes[0] = ;partypes[1] = ;Method meth = (add, partypes);method2 methobj = new method2();Object arglist[] = new Object[2];arglist[0] = new Integer(37);arglist[1] = new Integer(47);Object retobj = (methobj, arglist);Integer retval = (Integer) retobj;(());} catch (Throwable e) {(e);}}}假如一个程序在执行的某处的时候才知道需要执行某个方法,这个方法的名称是在程序的运行过程中指定的 (例如,JavaBean 开发环境中就会做这样的事),那么上面的程序展示了如何做到。 上例中,getMethod用于查找一个具有两个整型参数且名为 add 的方法。 找到该方法并创建了相应的Method 对象之后,在正确的对象实例中执行它。 执行该方法的时候,需要提供一个参数列表,这在上例中是分别包装了整数 37 和 47 的两个 Integer 对象。 执行方法的返回的同样是一个 Integer 对象,它封装了返回值 84。 7.创建新的对象对于构造器,则不能像执行方法那样进行,因为执行一个构造器就意味着创建了一个新的对象 (准确的说,创建一个对象的过程包括分配内存和构造对象)。 所以,与上例最相似的例子如下:import .*;public class constructor2 {public constructor2() {}public constructor2(int a, int b) {(a = + a + b = + b);}public static void main(String args[]) {try {Class cls = (constructor2);Class partypes[] = new Class[2];partypes[0] = ;partypes[1] = ;Constructor ct = (partypes);Object arglist[] = new Object[2];arglist[0] = new Integer(37);arglist[1] = new Integer(47);Object retobj = (arglist);} catch (Throwable e) {(e);}}}根据指定的参数类型找到相应的构造函数并执行它,以创建一个新的对象实例。 使用这种方法可以在程序运行时动态地创建对象,而不是在编译的时候创建对象,这一点非常有价值。 8.改变字段(域)的值reflection 的还有一个用处就是改变对象数据字段的值。 reflection 可以从正在运行的程序中根据名称找到对象的字段并改变它,下面的例子可以说明这一点:import .*;public class field2 {public double d;public static void main(String args[]) {try {Class cls = (field2);Field fld = (d);field2 f2obj = new field2();(d = + f2obj.d);(f2obj, 12.34);(d = + f2obj.d);} catch (Throwable e) {(e);}}}这个例子中,字段 d 的值被变为了 12.34。 9.使用数组本文介绍的 reflection 的最后一种用法是创建的操作数组。 数组在 Java 语言中是一种特殊的类类型,一个数组的引用可以赋给 Object 引用。 观察下面的例子看看数组是怎么工作的:import .*;public class array1 {public static void main(String args[]) {try {Class cls = ();Object arr = (cls, 10);(arr, 5, this is a test);String s = (String) (arr, 5);(s);} catch (Throwable e) {(e);}}}例中创建了 10 个单位长度的 String 数组,为第 5 个位置的字符串赋了值,最后将这个字符串从数组中取得并打印了出来。

es6新特性

ES6新特性是引入了块级作用域的概念。

这意味着变量和函数的作用域被限制在它们被声明的代码块内。块级作用域提供了更好的封装性和可读性,使得代码更易于理解和维护。这就让它可以包含属性和方法,使得对象的定义更加简洁明了。

ES6使得人们可以从数组或对象中提取数据并赋值给变量。这个功能使得代码更加简洁,可读性更强。这个特性使得函数的编写更加灵活,并且减少了因未提供参数而产生的错误。函数的编写更加灵活,可以处理任意数量的输入参数。

ES6的用处

Rest参数使得开发者可以接受任意数量的参数,并将其存储在一个数组中,为函数的编写提供了更大的灵活性。同时,箭头函数的引入也使得函数定义更加简洁,避免了this值在不同上下文中的歧义。

最后,ES6引入了模块化的概念,通过import和export语句来引入和导出模块,使得代码的组织和分割更加清晰有序,有利于代码的管理和维护。此外,Proxy对象、Generator函数和Iterator接口的引入也为开发者提供了更灵活的对象操作方式和数据遍历处理能力。

综上所述,ES6的引入极大地丰富了JavaScript的功能和语法,使得开发者可以更加高效、便捷地进行开发。无论是小型应用程序还是大型企业级应用,ES6都为开发者提供了强大的支持。

关于反射

在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。 也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。 每种语言的反射模型都不同,并且有些语言根本不支持反射。 Golang语言实现了反射,反射机制就是在运行时动态的调用对象的方法和属性,官方自带的reflect包就是反射相关的,只要包含这个包就可以使用。 多插一句,Golang的gRPC也是通过反射实现的。 在讲反射之前,先来看看Golang关于类型设计的一些原则 接下来要讲的反射,就是建立在类型之上的,Golang的指定类型的变量的类型是静态的(也就是指定int、string这些的变量,它的type是static type),在创建变量的时候就已经确定,反射主要与Golang的interface类型相关(它的type是concrete type),只有interface类型才有反射一说。 在Golang的实现中,每个interface变量都有一个对应pair,pair中记录了实际变量的值和类型: value是实际变量值,type是实际变量的类型。 一个interface{}类型的变量包含了2个指针,一个指针指向值的类型【对应concrete type】,另外一个指针指向实际的值【对应value】。 例如,创建类型为*的变量,然后将其赋给一个接口变量r: 接口变量r的pair中将记录如下信息:(tty, *),这个pair在接口变量的连续赋值过程中是不变的,将接口变量r赋给另一个接口变量w: 接口变量w的pair与r的pair相同,都是:(tty, *),即使w是空接口类型,pair也是不变的。 interface及其pair的存在,是Golang中实现反射的前提,理解了pair,就更容易理解反射。 反射就是用来检测存储在接口变量内部(值value;类型concrete type) pair对的一种机制。 既然反射就是用来检测存储在接口变量内部(值value;类型concrete type) pair对的一种机制。 那么在Golang的reflect反射包中有什么样的方式可以让我们直接获取到变量内部的信息呢? 它提供了两种类型(或者说两个方法)让我们可以很容易的访问接口变量内容,分别是() 和 (),看看官方的解释 ()是获取pair中的type,()获取pair中的value,示例如下: 当执行(interface)之后,就得到了一个类型为””变量,可以通过它本身的Interface()方法获得接口变量的真实内容,然后可以通过类型判断进行转换,转换为原有真实类型。 不过,我们可能是已知原有类型,也有可能是未知原有类型,因此,下面分两种情况进行说明。 已知类型后转换为其对应的类型的做法如下,直接通过Interface方法然后强制转换,如下: 示例如下: 很多情况下,我们可能并不知道其具体类型,那么这个时候,该如何做呢?需要我们进行遍历探测其Filed来得知,示例如下: 通过运行结果可以得知获取未知类型的interface的具体变量及其类型的步骤为: 通过运行结果可以得知获取未知类型的interface的所属方法(函数)的步骤为: 是通过(X)获得的,只有当X是指针的时候,才可以通过修改实际变量X的值,即:要修改反射类型的对象就一定要保证其值是“addressable”的。 示例如下: 这算是一个高级用法了,前面我们只说到对类型、变量的几种反射的用法,包括如何获取其值、其类型、如果重新设置新值。 但是在工程应用中,另外一个常用并且属于高级的用法,就是通过reflect来进行方法【函数】的调用。 比如我们要做框架工程的时候,需要可以随意扩展方法,或者说用户可以自定义方法,那么我们通过什么手段来扩展让用户能够自定义呢?关键点在于用户的自定义方法是未可知的,因此我们可以通过reflect来搞定 示例如下: Golang的反射很慢,这个和它的API设计有关。 在 java 里面,我们一般使用反射都是这样来弄的。 这个取得的反射对象类型是 。 它是可以复用的。 只要传入不同的obj,就可以取得这个obj上对应的 field。 但是Golang的反射不是这样设计的: 这里取出来的 field 对象是 类型,但是它没有办法用来取得对应对象上的值。 如果要取值,得用另外一套对object,而不是type的反射 这里取出来的 fieldValue 类型是 ,它是一个具体的值,而不是一个可复用的反射对象了,每次反射都需要malloc这个结构体,并且还涉及到GC。 Golang reflect慢主要有两个原因 上述详细说明了Golang的反射reflect的各种功能和用法,都附带有相应的示例,相信能够在工程应用中进行相应实践,总结一下就是:

若对本页面资源感兴趣,请点击下方或右方图片,注册登录后

搜索本页相关的【资源名】【软件名】【功能词】或有关的关键词,即可找到您想要的资源

如有其他疑问,请咨询右下角【在线客服】,谢谢支持!

ES6 Reflect:深入理解对象的反射操作 (es6reflect有什么用) 第2张

发表评论

评论列表

  • 这篇文章还没有收到评论,赶紧来抢沙发吧~
欢迎你第一次访问网站!