当前位置: 首页 > news >正文

【JS】Reflect

对象基本方法

JS语法操作对象时,本质上是调用一个内部封装好的函数,该函数中又会调用对象的基本方法,通过官方文档可以看到基本方法。在过去,这些对象的基本方法是不会对外暴露的。

在这里插入图片描述

如下面这段代码,使用JS语法给对象赋值,这种语法会触发JS内部方法,该方法最终会触发对象基本方法 [[Set]]

let obj = { name: "田本初" }
obj.age = 23

Reflect

Reflect 使开发者可以不使用JS语法的方式操作对象,而是直接调用对象基本方法

通过 mdn文档 可以看到基本方法对应 Reflect 的方法名,如 [[Get]] 对应 get(),[[Set]] 对应 set()。

在这里插入图片描述
这里以 [[Get]] 举例并通过 es文档 详细分析:

const obj = {a: 1,b: 2,get c() {return this.a + this.b}
}
console.log(obj.c); // 3
console.log(Reflect.get(obj, 'c')); // 3

[[Get]] 本身有两个参数,propertyKey为对象key, Receiver则为this指向。
通过JS语法(obj.key)读取对象时Receiver默认就是对象本身,无法修改this指向,但通过 Reflect 可以修改:

在这里插入图片描述

const obj = {a: 1,b: 2,get c() {return this.a + this.b}
}
console.log(obj.c); // 3
console.log(Reflect.get(obj, 'c', { a: 10, b: 20 })); // 30

Reflect 通常与 Proxy 配合使用,Proxy可以看本人另一篇文章:Object.defineProperty与Proxy的对比并通过Vue2、3的实现证明Proxy性能优于Object.defineProperty

下面举例,使用 Proxy 代理对象,此时 this 指向就会出现问题

const obj = {a: 1,b: 2,get c() {return this.a + this.b}
}const p = new Proxy(obj, {get(target, key) {console.log('get', key);return target[key];}
})p.c

在访问c时,虽然使用了a和b,但this仍指向原对象obj而非代理对象p,没有触发对a和b的监听,所以控制台只打印了c。使用 Reflect 手动更正 this 指向即可:

const obj = {a: 1,b: 2,get c() {return this.a + this.b}
}const p = new Proxy(obj, {get(target, key, receiver) {console.log('get', key);return Reflect.get(target, key, receiver);}
})p.c

在这里插入图片描述

再比如使用 Object.keys 获取对象键名集合时,默认会忽略类型为Symbol和不可枚举的属性。

在这里插入图片描述
查看 es文档 中Object.keys的实现

在这里插入图片描述
继续查看EnumerableOwnProperties,可以发现默认只取类型为string且可枚举的键

在这里插入图片描述

如果不想采用默认的 Object.keys 实现,可以通过 Reflect 直接使用对象的基本方法 [[OwnPropertyKeys]]

在这里插入图片描述

常用方法

  1. Reflect.apply(target, thisArgument, argumentsList)

    • 作用:调用一个目标函数,并指定 this 和参数。

    • 示例:

      function sum(a, b) {return a + b;
      }
      console.log(Reflect.apply(sum, null, [1, 2])); // 输出 3
      
  2. Reflect.construct(target, argumentsList[, newTarget])

    • 作用:等同于 new target(...argumentsList),但更具灵活性。

    • 示例:

      class MyClass {constructor(name) {this.name = name;}
      }
      const obj = Reflect.construct(MyClass, ['John']);
      console.log(obj.name); // 输出 'John'
      
  3. Reflect.defineProperty(target, propertyKey, attributes)

    • 作用:为对象定义属性,类似于 Object.defineProperty

    • 示例:

      const obj = {};
      Reflect.defineProperty(obj, 'name', {value: 'John',writable: true,configurable: true,enumerable: true
      });
      console.log(obj.name); // 输出 'John'
      
  4. Reflect.deleteProperty(target, propertyKey)

    • 作用:删除对象的属性,类似于 delete obj[propertyKey]

    • 示例:

      const obj = { name: 'John' };
      Reflect.deleteProperty(obj, 'name');
      console.log(obj.name); // 输出 undefined
      
  5. Reflect.get(target, propertyKey[, receiver])

    • 作用:获取对象的属性值,类似于 target[propertyKey]

    • 示例:

      const obj = { name: 'John' };
      console.log(Reflect.get(obj, 'name')); // 输出 'John'
      
  6. Reflect.set(target, propertyKey, value[, receiver])

    • 作用:设置对象的属性值,类似于 target[propertyKey] = value

    • 示例:

      const obj = {};
      Reflect.set(obj, 'name', 'John');
      console.log(obj.name); // 输出 'John'
      
  7. Reflect.has(target, propertyKey)

    • 作用:检查对象是否具有某个属性,类似于 propertyKey in target

    • 示例:

      const obj = { name: 'John' };
      console.log(Reflect.has(obj, 'name')); // 输出 true
      
  8. Reflect.ownKeys(target)

    • 作用:返回一个包含所有自身属性(包括不可枚举属性但不包括 Symbol 属性)的数组,类似于 Object.getOwnPropertyNamesObject.getOwnPropertySymbols 的组合。

    • 示例:

      const obj = { name: 'John', age: 30 };
      console.log(Reflect.ownKeys(obj)); // 输出 ['name', 'age']
      

与Proxy对比

Proxy可以看本人另一篇文章:Object.defineProperty与Proxy的对比并通过Vue2、3的实现证明Proxy性能优于Object.defineProperty

Reflect
只能调用对象的基本操作,比如属性的读取、设置、删除等。Reflect 不会对对象的行为做任何自定义或修改。它的作用只是将 JS 中的内置的对象基本操作标准化为方法,例如,Reflect.get() 只是返回对象的某个属性的值,不会更改对象的行为。

Proxy
用于 拦截和修改 对象。可以自定义对象的行为,甚至修改对象的默认操作(如属性读取、赋值等)。例如,使用 Proxy 的 get 捕捉器可以改变对象属性的获取方式,使得在读取属性时执行一些额外逻辑或返回自定义的值。


http://www.mrgr.cn/news/35610.html

相关文章:

  • 【Hadoop实训】Hive 数据操作②
  • 七牛云上传图片成功,但是无法访问显示{error : document not found}
  • 简析大模型参数高效微调方法
  • The 3rd Universal CupStage 15: Chengdu, November 2-3, 2024(2024ICPC 成都)
  • 基于Java和Vue实现的顺风车拼车系统打车约车平台拼车软件
  • 「QT」顺序容器类 之 QVector 动态数组类
  • Java后端开发中的RESTful API版本控制策略
  • uniapp js向json中增加另一个json的全部数据,并获取json长度
  • Elasticsearch7.7修改network.host IP地址 start启动失败及Elasticsearch7的配置项详解
  • 栈的深度解析:顺序栈与链栈的实现
  • Oracle逻辑备份脚本【生产环境适用】
  • 苏轼为何要写石钟山记?时间节点是关键
  • 问:Java线程为不直接run(),而是要先Start()?
  • service 命令:管理系统服务
  • 数据结构 ——— 数组 nums 包含了从 0 到 n 的所有整数,但是其中缺失了一个,请编写代码找出缺失的整数,并且在O(N)时间内完成
  • 【C++前缀和 状态压缩】1177. 构建回文串检测|1848
  • 车辆识别数据集,图片数量20500,模型已训练200轮
  • C语言 | Leetcode C语言题解之第435题无重叠区间
  • TCP/IP 协议栈
  • 使用TensorFlow实现一个简单的神经网络:从构建到训练
  • 240924-通过服务器代理ip地址及port端口wget等下载文件
  • RT-DETR改进策略:BackBone改进|PoolFormer赋能RT-DETR,视觉检测性能显著提升的创新尝试
  • 在Java中,关于final、static关键字与方法的重写和继承【易错点】
  • 点亮城市安全:高科技助力精准定位路灯漏电‘隐形杀手
  • 2024年CSP-J认证 CCF信息学奥赛C++ 中小学初级组 第一轮真题-阅读程序题解析
  • 实战OpenCV之图像滤波