Proxy和Reflect

Proxy和Reflect

  1. 拦截操作
    • get(target,propKey,receiver) 读取属性时拦截
      • 拦截器对不可配置(configurable:false)且不可写(writable:false)的属性读取报错
    • set(target,propKey,value,receiver) 设置属性时拦截
      • 拦截器对不可配置(configurable:false)且不可写(writable:false)属性的修改操作无效
    • has(target,propKey) in操作时拦截
      • 拦截器对不可配置(configurable:false)的属性或者禁止扩展的对象in操作返回"如果有但是改写成false"报错
      • propKey in proxy
    • deleteProperty(target,propKey) delete操作时拦截
      • 不可配置(configurable:false)属性删除时报错
      • delete proxy[propKey]
    • ownKeys(target) 遍历操作时拦截
      • 不可配置的属性必须被返回,否则报错
      • 不可扩展对象只能返回所有原有配置属性
      • Object.getOwnPropertyNames(proxy)
      • Object.getOwnPropertySymbols(proxy)
      • Object.keys(proxy)
      • for (let key in proxy)
      • Reflect.ownKeys(proxy)
    • getOwnPropertyDescriptor(target,propKey) 获取属性描述时拦截,在未设置set拦截器时,设置属性也会进入getOwnPropertyDescriptor拦截
      • Object.getOwnPropertyDesctiptor(proxy,propKey)
      • Object.getOwnPropertyDescriptors(proxy)
    • defineProperty(target,propKey,propDesc) 定义属性时拦截
      • 不可修改不可写或者不可配置的属性
      • 不可为不可扩展对象增加属性
      • Object.defineProperty(proxy,propKey,propDesc)
      • Object.defineProperties(proxy,propDescs)
    • preventExtensions(target) 使对象变成不可扩展时拦截
      • Object.preventExtensions(proxy)
    • isExtensible(target) 查看对象是否是不可扩展对象时拦截
      • 返回值必须和目标对象的isExtensible属性一致
      • Object.isExtensible(proxy)
    • getPrototypeOf(target) 获取对象的原型对象时拦截
      • 不可扩展对象必须返回目标对象的原型对象
      • Object.getPrototypeOf(proxy)
      • Refelect.getPrototypeOf(proxy)
      • proxy instanceof Object
      • proxy.__proto__
      • Object.prototype.isPrototypeOf(proxy)
    • setPrototypeOf(target,proto)设置对象的原型对象时拦截
      • 不可扩展对象不可改变目标对象原型
      • Object.setPrototypeOf(proxy,proto)
    • apply(target,object,args)实例作为函数调用时拦截
      • proxy(...args)
      • proxy.call(object,...args)
      • proxy.apply(object,args)
      • Reflect.apply(proxy,object,args)
    • construct(target,args,newTarget)实例作为构造函数调用时拦截
      • newTarget默认是代理后的对象
      • new proxy(...args)
  2. Proxy.revocable()
        const proxy = Proxy.revocable({},{})
        proxy.proxy //代理实例
        peoxy.revoke() //取消代理
    
  3. 所有拦截操作在Reflect对象上都有对应的同名方法来完成默认操作

tips

  1. get,set拦截方法里的receiver指向当前操作所在的对象
        const proxy = new Proxy({},{
            get(target,propKey,receiver){
                return receiver
            }
        })
        let obj = Object.create(proxy)
        proxy.a === proxy // true
        obj.a === obj // true
    
  2. get生成dom
     const dom = new Proxy({},{
         get(target,property){
             return (attrs={},...children)=>{
                 /*生成节点*/
                 let el = document.createElement(property)
                 /*设置属性*/
                 for(let prop of Object.keys(attrs)){
                     el.setAttribute(prop,attrs[prop])
                 }
                 for(child of children){
                     /*生成子节点*/
                     if(typeof child === 'string'){
                         child = document.createTextNode(child)
                     }
                     el.appendChild(child)
                 }
                 return el
             }
         }
     })
     const el = dom.div({},
         'Hello, my name is ',
         dom.a({href: '//example.com'}, 'Mark'),
         '. I like:',
         dom.ul({},
             dom.li({}, 'The web'),
             dom.li({}, 'Food'),
             dom.li({}, '…actually that\'s it')
         )
     );
     document.body.appendChild(el); 
    
  3. 通过Proxy的set方法可以监听到数据变更,可以在set方法里执行相应的处理函数来实现观察者模式

你可能感兴趣的:(Proxy和Reflect)