• ES6——Proxy与Reflect


    • Proxy

      可以对目标对象的读取、函数等操作进行拦截,然后进行操作处理。它不直接操作函数对象,而是像代理模式,通过对象的代理对对象进行操作,在进行这些操作时,可以增加一些需要的额外操作

      • 基本用法

        let target = {
            name: 'Tom',
            age: 24
        }
        let header = {
            get: function (target,key) {
                console.log('getting'+key)
                return target[key]	//注意只能用target[key],不能使用target.key
            },
            set: function (target,key,value) {
                console.log('setting'+key)
                target[key] = value
        
            }
        }
        //生成target的代理对象,对目标对象进行了浅拷贝,因此目标对象和代理对象相互影响
        let proxy = new Proxy(target,header)
        proxy.name      //实际执行的是 hander.get
        console.log(proxy.age = 18)  //实际执行的是 hander.set
        
      • 实例方法

        • get(target,propKey,receiver)

          拦截读取操作

          target: 目标对象

          propKey: 属性

          receiver: Proxy 对象本身

        • set(target,propKey,value,receiver)

          拦截赋值操作

          value: 新赋的值

        • apply(target,ctx,args)

          拦截函数调用、call 和 apply 操作

          ctx: 目标对象上下文

          args: 目标对象参数数组

        • has(target,propKey)

          拦截 HasProperty 操作,即在判断 target 对象是否存在 propKey 属性,会被该方法拦截。但次方法不拦截 for...in 操作

          let hanlder = {
              has: function(target,propKey){
                  console.log("handle has")
                  return propKey in target
              }
          }
          let exam = {name: 'Tom'}
          let proxy = new Proxy(exam,handler)
          "name" in proxy	//handle 	//true
          
        • deleteProperty(target,propKey)

          拦截 delete 操作,如果这个方法抛出异常或返回 false ,propKey 属性将无法被 delete 命令删掉

        • construct(target,args)

          拦截 new 命令,返回值必须是对象

        • defineProperty(target,propKey,propDesc)

          拦截 Object.defineProperty , 若目标不可扩展,增加目标对象上不存在的属性会报错,若属性不可写或不可配置,则不能改变这些属性

        • getOwnPropertyDescriptor(target,propKey)

          拦截 Object.getOwnPropertyDescriptor() ,返回值为属性描述对象或者 undefined

          let handler = {
              getOwnPropertyDescriptor: function(target, propKey){
                  return Object.getOwnPropertyDescriptor(target, propKey);
              }
          }
          let target = {name: "Tom"}
          let proxy = new Proxy(target, handler)
          Object.getOwnPropertyDescriptor(proxy, 'name')
          // {value: "Tom", writable: true, enumerable: true, configurable: true}
          
        • getPrototypeOf(target)

          拦截获取对象原型操作

          //包括以下操作
          Object.prototype.__proto__
          Object.prototype.isPrototypeOf()
          Object.getPrototypeOf()
          Reflect.getPrototypeOf()
          instanceof
          

          返回值必须是对象或 null

        • isExtensible(target)

          用于拦截 Object.isExtensible --> 是否是可扩展的

          返回值只能是 boolean 值

        • ownKeys(target)

          用于拦截对象自身属性的读取操作

          //包括以下操作
          Object.getOwnPropertyNames()
          Object.getOwnPropertySymbols()
          Object.keys()
          or...in
          
    • Reflect

      用于获取目标对象行为,与 Object 类似,方法与 Proxy 对应

      • 方法

        • Reflect.get(target,name,receiver)

          查找并返回 target 对象的 name 属性

          let exam = {
              name: "Tom",
              age: 24,
              get info(){
                  return this.name + this.age;
              }
          }
          Reflect.get(exam, 'name'); // "Tom"
           
          // 当 target 对象中存在 name 属性的 getter 方法, getter 方法的 this 会绑定 // receiver
          let receiver = {
              name: "Jerry",
              age: 20
          }
          Reflect.get(exam, 'info', receiver); // Jerry20
           
          // 当 name 为不存在于 target 对象的属性时,返回 undefined
          Reflect.get(exam, 'birth'); // undefined
           
          // 当 target 不是对象时,会报错
          Reflect.get(1, 'name'); // TypeError
          
        • Reflect.set(target,name,value,receiver)

          将 target 的 name 属性设置为 value ,返回值为 boolean ,true 表示修改成功, false 表示修改失败。当 target 为不存在的对象时,会报错

        • Reflect.has(obj,name)

          name in obj 指令的函数化,用于查找 name 属性在 obj 对象中是否存在。返回值是 boolean 。如果 obj 不是对象会报错 TypeError

        • Reflect.deleteProperty(obj,property)

          delete obj[property] 的函数化,用于删除 obj 对象的 property 属性,返回值为 boolean 。

        • Reflect.construct(obj,args)

          等同于 new target(...args)

        • Reflect.getPrototype(target)

          用于读取 obj 的 __proto__ 属性。在 obj 不是对象时不会像 Object 一样把 obj 转为对象,而是会报错

        • Reflect.setPrototype(target,newProto)

          用于设置目标对象的 prototype

        • Reflect.apply(func,thisArg,args)

          等同于Function.prototype.apply.call(fun,thisArg,args)。func 表示目标函数;thisArg 表示目标函数绑定的 this 对象;args 表示目标函数调用时传入的参数列表,可以是数组或类似数组的对象。若目标函数无法调用,会抛出 TypeError

        • Reflect.defineProperty(target,propKey,attributes)

          用于为目标对象定义属性。如果 target 不是对象,会抛出错误

        • Reflect.getOwnPropertyDescriptor(target,propKey)

          用于得到 target 对象的 propKey 属性的描述对象

        • Reflect.isExtensible(target)

          用于判断 target 对象是否为可扩展。返回值为 boolean

        • Reflect.preventExtensions(target)

          用于让 target 对象变为不可扩展。

        • Reflect.ownKeys(target)

          用于返回 target 返回的所有属性

    • 组合使用

      Reflect 对象的方法和 Proxy 对象的方法是一一对应的。所有 Proxy 对象的方法可以通过调用 Reflect 对象的方法获取默认行为,然后进行额外操作

      let exam = {
          name: "Tom",
          age: 24
      }
      let handler = {
          get: function(target, key){
              console.log("getting "+key);
              return Reflect.get(target,key);
          },
          set: function(target, key, value){
              console.log("setting "+key+" to "+value)
              Reflect.set(target, key, value);
          }
      }
      let proxy = new Proxy(exam, handler)
      proxy.name = "Jerry"
      proxy.name
      // setting name to Jerry
      // getting name
      // "Jerry"
      
      • 实现观察者模式

        // 定义 Set 集合
        const queuedObservers = new Set();
        // 把观察者函数都放入 Set 集合中
        const observe = fn => queuedObservers.add(fn);
        // observable 返回原始对象的代理,拦截赋值操作
        const observable = obj => new Proxy(obj, {set});
        function set(target, key, value, receiver) {
          // 获取对象的赋值操作
          const result = Reflect.set(target, key, value, receiver);
          // 执行所有观察者
          queuedObservers.forEach(observer => observer());
          // 执行赋值操作
          return result;
        }
        
  • 相关阅读:
    MEAN: AngularJS + NodeJS的REST API开发教程
    什么是MEAN全堆栈javascript开发框架
    fputcsv 导出excel,解决内存、性能、乱码、科学计数法问题
    React 高德地图画点画区域放大缩小
    React 拖动布局
    React+TypeScript搭建项目
    js 运算符优先级
    for...in 与 for...of
    前端面试点记录
    Vue 高德地图 路径规划 画点
  • 原文地址:https://www.cnblogs.com/angle-yan/p/13379192.html
Copyright © 2020-2023  润新知