Proxy

Proxy

在ES6之前Object.defineProperty可以拦截对象属性的读取修改操作,Proxy 可以理解成比这个API更强大的,在目标对象之前架设一层的“拦截”。外界对该Proxy对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

注意:只有对生成的 Proxy 实例操作才能起到拦截的作用

生成Proxy实例:

 let proxy = new Proxy(target, handler)
  • target :需要代理的对象
  • handler :拦截函数的集合

如果handler空对象则代表任何操作都不会拦截

 	let obj = {}
    
    /*handler为空对象*/
    let proxy = new Proxy(obj, {})
    proxy.a = 1
    //obj.a  //1

对属性的读取进行拦截:

  let proxy = new Proxy({}, {
      get: function(target, property) {
        return 35
      }
    })
    
    proxy.time // 35
    proxy.name // 35
    proxy.title // 35

下面是 Proxy 支持的拦截操作一览,一共 13 种。

  • get(target, propKey, receiver):拦截对象属性的读取,比如proxy.fooproxy['foo']
  • set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy[‘foo’] = v,返回一个布尔值
  • has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值
  • deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值
  • ownKeys(target):拦截Object.getOwnPropertyNames(proxy)Object.getOwnPropertySymbols(proxy)Object.keys(proxy)for...in循环返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性
  • getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey)返回属性的描述对象
  • defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)Object.defineProperties(proxy, propDescs)返回一个布尔值
  • getPrototypeOf(target):拦截Object.getPrototypeOf(proxy)返回一个对象
  • setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto)返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
  • apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)proxy.call(object, ...args)proxy.apply(...)
  • construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)
  • isExtensible(target):拦截Object.isExtensible(proxy)返回一个布尔值
  • preventExtensions(target):拦截Object.preventExtensions(proxy)返回一个布尔值
  • target : 目标对象
  • property:引用的目标对象上的字符串键属性
  • value: 要赋给属性的值
  • receiver: 接收最初赋值的对象
let obj = {
  name: 'zs',
  age: 18
}
let proxy = new Proxy(obj, {
  get: function (target, property) {
    console.log('读取')
    console.log('读取target', target)
    console.log('读取property', property)
  },
  set: function (target, propKey, value, receiver) {
    console.log('target', target)
    console.log('propKey', propKey)
    console.log('value', value)
    console.log('receiver', receiver)
    if (value > 18 && propKey === 'age') {
      console.log('可以修改为大于18')
      target[propKey] = value
    } else {
      target[propKey] = target[propKey]
      console.log('不可以修改为小于18')
    }
  }
})

 proxy.age = 10
// log
 target {name: "zs", age: 18}
 propKey age
 value 10
 不可以修改为小于18
// obj {name: "zs", age: 18}
 proxy.age = 20
 // log
 target {name: "zs", age: 18}
 propKey age
 value 20
 receiver Proxy {name: "zs", age: 18}
 可以修改为大于18
// obj {name: "zs", age: 20}

Proxy给了开发者拦截语言默认行为的权限,可以不改变原有对象或函数的情况下,轻松运用在很多场景。例如:统计函数调用次数,实现响应式数据观测(Vue 3.0),实现不可变数据(Immutable)等等

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值