ES6_proxy_note

  • proxy:代理

Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程

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

主要是扩展 / 增强 对象的一些功能

比如说 Vue中的 Vue.key.Codes.enter=65


proxy作用:

Vue中的拦截,上报,扩展功能,统计,增强功能等的

proxy是设计模式的一中,代理模式


语法:
new Proxy(target,handler);

let obj = new Proxy(被代理的对象,对对立对象的操作)

  • 注意:被代理的对象可以是null

    hander是一个json:
<script >
   {
   set(){},//设置的时候干的事
   get(){},// 获取对象属性
   deleteProperty(){},//删除
   has(){},//判断有没有
   apply(){}//调用函数的处理
   // 等等
   }
</script>

如:利用proxy创建元素:

<script >
   const DOM = new Proxy({}, {
       get(target, property) {
           // property 就是 DOM.xx 里面的xxx
           // console.log(target, property);
           // ...:扩展剩余参数
           return function (attr = {}, ...children) {
               // console.log(attr, children);
               const el = document.createElement(property);
               for (let key of Object.keys(attr)) {
                   // 为el添加属性
                   el.setAttribute(key, attr[key]);
               }
               //再添加子元素
               for (let child of children) {
                   if (typeof child == 'string') {
                       child = document.createTextNode(child);
                   }
                   el.appendChild(child);
               }
               return el;
           }
       }
   });
   let oDiv = DOM.div({id: 'div1', class: 'aaa'}, '我是div', '呵呵呵');
   console.log(oDiv);
</script>

利用proxy创建元素及其子元素:

<script >
   const DOM = new Proxy({}, {
       get(target, property) {
           // property 就是 DOM.xx 里面的xxx
           // console.log(target, property);
           // ...:扩展剩余参数
           return function (attr = {}, ...children) {
               // console.log(attr, children);
               const el = document.createElement(property);
               for (let key of Object.keys(attr)) {
                   // 为el添加属性
                   el.setAttribute(key, attr[key]);
               }
               //再添加子元素
               for (let child of children) {
                   if (typeof child == 'string') {
                       child = document.createTextNode(child);
                   }
                   el.appendChild(child);
               }
               return el;
           }
       }
   });
   //只要用DOM创建元素就调用了代理
   let oDiv = DOM.div({id: 'div1', class: 'aaa'}, '我是div', '呵呵呵');
   console.log(oDiv);
</script>

使用set进行拦截 和
实现一个,访问对象身上的属性,默认不存在的时候返回undefined,希望如果不存在,返回错误(警告)信息,如:

<script >
   { // 使用set进行拦截
       let obj = new Proxy({}, {
           set(target, prop, value) {
               console.log(target, prop, value);
           }
       });
       obj.a = 132;
       console.log("split---");
   }
   // 设置一个年龄保证为整数,大于18,不能超过200
   let obj = new Proxy({}, {
       set(target, prop, value) {
           if (prop == 'age') {
               if (!Number.isInteger(value)) {
                   throw new TypeError(`年龄必须为整数`);
               }
               if (value > 200) {
                   throw new RangeError(`年龄超标了,必须小于200岁`);
               }
           }
           target[prop] = value;
       }
   });
   obj.a = 123;
   obj.name = 'kirin';
   console.log(obj);
   // 报错
   // obj.age = 13.5;
   obj.age = 13;

   /*
   deleteProperty():删除,拦截
   has():检测有没有
   * */
</script>

利用proxy删除与判断:

<script >
   let json = {
       a: 1,
       b: 2
   };
   let newJson = new Proxy(json, {
       deleteProperty(target, property) {
           console.log(`你要删除${property}属性`);
           //TODO
           delete target[property];
       },
       has(target, property) {
           console.log(`你判断是否存在,调用has方法了`);
           //TODO
           return property in target;
       }
   });
   console.log('a' in newJson);
   delete newJson.a;
   console.log(newJson);
</script>

apply():拦截方法

<script >
   function fn() {
       return `我是函数`;
   }

   let newFn = new Proxy(fn, {
       apply(target, thisArg, argArray) {
           return `函数吗?`
       }
   });
   console.log(newFn());
</script>

Reflect.apply(调用的函数,this指向,参数数组);
利用apply进行拦截方法:

<script >
   function sum(a, b) {
       return a + b;
   }

   let newSum = new Proxy(sum, {
       apply(target, context, args) {
           // context:指向
           // console.log(target, context, args);
           // console.log(...arguments)
           // Reflect:反射
           return Reflect.apply(...arguments)**2;
       }
   })
   console.log(newSum(2, 3));
</script>

还有:

<script >
   // console.log(Math.ceil(5.4));

   // let rel = Reflect.apply(Math.ceil, null, [9.8]);
   // console.log(rel);

   function show(...args) {
       console.log(this)
       console.log(args);
   }

   // show(1,2,3,4);
   // show.call('abc', 1, 2, 3, 4);
   // show.apply('abc', [1, 2, 3, 4]);
   Reflect.apply(show, 'aaaa', [1, 2, 3, 4]);
</script>

Reflect:反射

<script >
   // 之前的检测方法
   console.log('assign' in Object);
   // 以后的检测方法可能一直是:
   console.log(Reflect.has(Object, 'assign'));
</script>

还有:

<script >
   let json = {a: 1, b: 2};
   /*delete json.a;//删除
   console.log(json);*/
   Reflect.deleteProperty(json, 'a');//删除
   console.log(json);
</script>

Object.xxxx 语言内部的方法

Object.defineProperty

放到Reflect对象身上

通过Reflect对象身上直接拿到语言内部东西

上一篇:面向对象设计-微信联系人


下一篇:note-STM32(macOS)