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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

田本初

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值