Js:Proxy(Vue3响应式原理)、Reflect(源码中应用多)

文章详细介绍了JavaScriptES6中的Proxy类和Reflect对象,包括Proxy用于创建代理对象以拦截和修改对象操作,如get、set等13种捕获器。同时讲解了Reflect对象的用途,它是对JavaScript操作对象的规范化,提供与Proxy对应的方法,用于在不直接操作原对象的情况下进行对象操作。
摘要由CSDN通过智能技术生成

1、Proxy类

1. 概括

Proxy是一个类,基本使用:

const p = new Proxy(target, handler)
  1. 首先,我们需要new Proxy对象,并且传入需要侦听的对象以及一个处理对象,可以称之为handler
  2. 其次,我们之后的操作都是直接对Proxy的操作,而不是原有的对象,因为我们需要在handler里面进行侦听(添加捕获器)

2. 捕获器

如果我们想要侦听某些具体的操作,那么就可以在handler中添加对应的捕捉器(Trap):

setget分别对应的是函数类型;

  • set函数有四个参数:
    • target:目标对象(侦听的对象);
    • property:将被设置的属性key;
    • value:新属性值;
    • receiver:调用的代理对象(生成的代理对象);
  • get函数有三个参数:
    • target:目标对象(侦听的对象);
    • property:被获取的属性key;
    • receiver:调用的代理对象;
  <script>
    const obj = {
      name: "why",
      age: 18,
      height: 1.88
    }


    // 1.创建一个Proxy对象
    const objProxy = new Proxy(obj, {
      set: function(target, key, newValue) {
        console.log(`监听: 监听${key}的设置值: `, newValue)
        target[key] = newValue
      },
      get: function(target, key) {
        console.log(`监听: 监听${key}的获取`)
        return target[key]
      }
    })

    // 2.对obj的所有操作, 应该去操作objProxy
    console.log(objProxy.name)
    objProxy.name = "kobe"
    console.log(objProxy.name)

    objProxy.address = "广州市"
    console.log(objProxy.address)

  </script>

3. 其他捕获器(共13个)

  1. handler.getPrototypeOf()
    • Object.getPrototypeOf 方法的捕捉器。【获取对象原型】
  2. handler.setPrototypeOf()
    • Object.setPrototypeOf 方法的捕捉器。【设置对象原型】
  3. handler.isExtensible()
    • Object.isExtensible 方法的捕捉器【判断是否可以新增属性】。
  4. handler.preventExtensions()
    • Object.preventExtensions 方法的捕捉器【阻止新增属性】。
  5. handler.getOwnPropertyDescriptor()
    • Object.getOwnPropertyDescriptor 方法的捕捉器。
  6. handler.defineProperty()
    • Object.defineProperty 方法的捕捉器。
  7. handler.ownKeys()
    • Object.getOwnPropertyNames 方法和Object.getOwnPropertySymbols 方法的捕捉器。
  8. handler.has()
    • in 操作符的捕捉器。
  9. handler.get()
    • 属性读取操作的捕捉器。
  10. handler.set()
    • 属性设置操作的捕捉器。
  11. handler.deleteProperty()
    • delete 操作符的捕捉器。
  12. handler.apply()
    • 函数调用操作的捕捉器。
  13. handler.construct()
    • new 操作符的捕捉器。

2、Reflect对象

1. 概括

Reflect也是ES6新增的一个API,它是一个对象,字面的意思是反射

那么这个Reflect有什么用呢?

  • 它主要提供了很多操作JavaScript对象的方法,有点像Object中操作对象的方法;
  • 比如Reflect.getPrototypeOf(target)类似于 Object.getPrototypeOf();

如果我们有Object可以做这些操作,那么为什么还需要有Reflect这样的新增对象呢?

  • 这是因为在早期的ECMA规范中没有考虑到这种对象本身 的操作如何设计会更加规范,所以将这些API放到了Object上面
  • 但是Object作为一个构造函数,这些操作实际上放到它身上并不合适;
  • 另外还包含一些类似于 indelete操作符,让JS看起来是会有一些奇怪的;
  • 所以在ES6中新增了Reflect,让我们这些操作都集中到了Reflect对象上;
  • 另外在使用Proxy时,可以做到不操作原对象;

总结:

  1. 早期考虑不周,导致Object越来越臃肿,所以加了Reflect对象,它跟Object对象的API只有细微差别。主要是为了规范代码用
  2. 实际开发用的不多,在一些源码上会用到

Object和Reflect对象之间的API关系,可以参考MDN文档
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect

2. Reflect的使用:和Proxy共同完成代理

ReflectProxy是一一对应的,也是13个方法,这里以set方法为例:

  <script>

    const obj = {
      _name: "why",
      set name(newValue) {
        console.log("this:", this) // 默认是obj,【receiver】改变的是这里的this指向,改为指向代理对象objProxy
        this._name = newValue
      },
      get name() {
        return this._name
      }
    }

    const objProxy = new Proxy(obj, {
      set: function(target, key, newValue, receiver) {
        // target[key] = newValue
        // 1.好处一: 代理对象的目的: 不再直接操作原对象
        // 2.好处二: Reflect.set方法有返回Boolean值, 可以判断本次操作是否成功
        /*
           3.好处三:
             > receiver就是外层Proxy对象
             > Reflect.set/get最后一个参数【receiver】, 可以决定对象访问器setter/getter的this指向,实现两次监听
                >1. 第一次监听是 调用set方法
                >2. 第二次监听是 set方法里的this赋值
        */
        console.log("proxy中设置方法被调用")
        const isSuccess = Reflect.set(target, key, newValue, receiver)

        if (!isSuccess) {
          throw new Error(`set ${key} failure`)
        }
      },
      get: function(target, key, receiver) {
        console.log("proxy中获取方法被调用")
        return Reflect.get(target, key, receiver)
      }
    })


    // 操作代理对象
    // objProxy.name = "kobe"
    console.log(objProxy.name)

  </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值