ChuChencheng / note

菜鸡零碎知识笔记
Creative Commons Zero v1.0 Universal
3 stars 0 forks source link

ES6 Proxy #24

Open ChuChencheng opened 4 years ago

ChuChencheng commented 4 years ago

概念

用于修改某些操作的默认行为,等同于在语言层面做出修改。相当于在目标对象之前架设一层“拦截”,外部对对象的操作,必须通过这层拦截,可对操作进行过滤和改写。

const proxyObject = new Proxy({}, {
  get (target, key, receiver) {
    // target: 目标对象
    // key: 当前获取的键
    // receiver: 当前 Proxy 对象
    console.log('getting ', key)
    return Reflect.get(target, key, receiver)
  },
  set (target, key, value, receiver) {
    // value 当前设置的值
    console.log('setting ', key)
    return Reflect.set(target, key, value, receiver)
  },
})

proxyObject.a = 1 // setting a

proxyObject.a++
// getting a
// setting a
// 1

Proxy 的 13 种拦截操作

具体参数说明与用法,可参考各类文档,例如 MDN , typescript 定义,http://es6.ruanyifeng.com/#docs/proxy 等。

Proxy.revocable()

定义:

revocable<T extends object>(target: T, handler: ProxyHandler<T>): { proxy: T; revoke: () => void; }

返回一个可取消的 Proxy 实例

const { proxy, revoke } = Proxy.revocable({}, {})

proxy.a = 1
proxy.a // 1

revoke()

proxy.a // TypeError: Cannot perform 'get' on a proxy that has been revoked

可应用于不允许直接访问对象,必须通过代理访问,访问结束后就收回代理,不能再次访问的场景。

this

Proxy 中的 this 指向的是 proxy ,而不是原对象,因此,即使 handler 是空的,什么也不拦截,其 proxy 的表现与原对象也不是完全一致的。

const target = {
  f () {
    return this
  }
}

const proxy = new Proxy(target, {})

target.f() === target // true
proxy.f() === target // false
proxy.f() === proxy // true

此外,一些原生对象的内部属性,只有通过正确的 this 才能拿到,例如 Date

const target = new Date()
const proxy = new Proxy(target, {})

proxy.getDate() // TypeError: this is not a Date object

如果把 this 绑定回原来的对象,就可以正常使用:

const target = new Date()
const proxy = new Proxy(target, {
  get (target, key) {
    if (key === 'getDate') {
      // 判断是否调用的 getDate 方法
      return target.getDate.bind(target)
    }
    return Reflect.get(target, key)
  }
})

proxy.getDate() // 正常显示日期

参考

http://es6.ruanyifeng.com/#docs/proxy