首页 > 其他分享 >【JS】Reflect

【JS】Reflect

时间:2024-09-26 10:20:39浏览次数:3  
标签:obj name get 对象 JS Reflect target

对象基本方法

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 捕捉器可以改变对象属性的获取方式,使得在读取属性时执行一些额外逻辑或返回自定义的值。

标签:obj,name,get,对象,JS,Reflect,target
From: https://blog.csdn.net/owo_ovo/article/details/142492091

相关文章

  • 深入理解 JSX:构建 React 用户界面的利器
    目录一、JSX介绍1.JSX概念2.为什么使用JSX,JSX有什么好处?二、JSX基本语法1.基本元素: 2.嵌套元素:3.组件:4.属性: 5.表达式6.条件渲染:7.样式:三、JSX语法规则四、JSX编译过程五、JSX小案例1.待办事项列表2.计时器应用六、总结一、JSX介绍1.JSX概念    ......
  • 基于SpringBoot+MySQL+SSM+Vue.js的智能停车计费系统设计与实现(附论文)
    获取见最下方名片信息获取见最下方名片信息获取见最下方名片信息演示视频基于SpringBoot+MySQL+SSM+Vue.js的智能停车计费系统设计与实现(附论文)技术描述开发工具:Idea/Eclipse数据库:MySQLJar包仓库:Maven前端框架:Vue/ElementUI后端框架:Spring+SpringMVC......
  • 【粉丝福利社】循序渐进Vue.js 3.x前端开发实践
    ......
  • 925 jdbc js 链表(2)
    jdbc基础复习一遍js声明函数行为绑定onclick单击ondbclick双击script标签放head以外也可以script必须写双标签变量声明都用var弱类型console。log1==1true1==‘1’trueprompt弹窗输入for循环js创建对象......
  • tagcloud.js 实现3d 云标签
    我这个布局是准备在中间放一张图片,两边的便签在图片的左右两边区域动。中间图片自己放,每个标签鼠标放上去会放大并停止。效果如下:3d云标签注意:标签样式可以自行修改,tagcloud参数配置中,如果有的标签在区域内边界会被遮住,就通过radius和direction调节即可。完整代码如下......
  • 前端mjs和js文件区别
    .js文件和.mjs文件之间的主要区别在于模块系统的使用:1.模块类型.js文件:默认使用CommonJS模块系统(尤其在Node.js环境中)。可以使用require()导入模块和module.exports导出模块。.mjs文件:明确表示使用ES6模块系统(ECMAScriptModules)。使用import和e......
  • 基于autojs的多平台多功能养号+获客+高级UI界面的软件
    1.项目介绍源码已经完成了完整RPA产品的开发,可进行二次开发或者个人使用其中包括高级UI界面和UI逻辑xhs,快手,微信视频号,抖音的完整养号功能10大针对平台定制化的截流获客功能卡密系统验证对接与日期显示无障碍自启定时启动可穿透悬浮窗功能历史运行日志github软件项目下载......
  • 04 JSON 序列化 反序列化
    `#!/usr/bin/envpython#-*-coding:utf-8-*-#@File:json字符串-序列化-反序列化.py#@Author:jhchena#@Date:2024/8/18#@Desc:#@Contact:[email protected]=[11,22,33,44]#python转换成json格式-序列化dic_string=......
  • nodejs发展历程
    Node.js的发展历程:2009年:Node.js由RyanDahl在"JSConf"会议上首次发布。2010年:Express框架和Socket.io实时通信库诞生。2011年:npm发布1.0版本,大公司如LinkedIn、Uber开始采用Node.js,同时hapi框架诞生。2012年:Node.js的普及速度非常快。2013年:Ghost成为......
  • laravel: 报错:Uncaught ReflectionException: Class "view" does not exist
    一,报错信息:UncaughtReflectionException:Class"view"doesnotexistin/web/api/vendor/laravel/framework/src/Illuminate/Container/Container.php:938Stacktrace:#0/web/api/vendor/laravel/framework/src/Illuminate/Container/Container.php(938):Refl......