当前位置:   article > 正文

Es6新特性Proxy代理用法解析_es6 proxy

es6 proxy

一.什么是Proxy:

  1. Proxy 对象是ES6新出的一个特性,用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
  2. 需要知道的是,在Vue2中双向数据绑定原理(数据劫持)采用Object.defineProperty,而在Vue3中数据劫持原理采用的是Proxy代理。

为什么Proxy会取代Object.defineProperty:

  1. Object.defineProperty只能劫持对象的属性,不能监听数组。也不能对 es6 新产生的 Map,Set 这些数据结构做出监听。也不能监听新增和删除操作等等。
  2. Proxy可以直接监听整个对象而非属性,可以监听数组的变化,具有多达13中拦截方法。

使用:

let p = new Proxy(target, handler);
  • 1

 其中参数 target 为包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
 其中参数 handler 为具体操作,其实就是一个对象,其属性是当执行一个操作时定义代理的行为的函数。就是说里面写各种拦截的函数。不同的拦截方法拦截的是不同的操作。

二.具体拦截方法:

1.get方法:

 get(target, property, receiver)方法用于拦截某个属性的读取操作,可以接受三个参数,分别为目标对象、属性名和 proxy 实例本身。看下面例子能不能拦截:

      let obj = { name: "jack", age: "20" };
     // 给obj设置一个代理
      let p = new Proxy(obj, {
        get(target, property) {
          console.log("我拦截了" + target + "读取" + property);
          console.log("它的值为" + target[property]);
          // 定义你要返回的值
          return target[property];
        },
      });
      
      //读取obj的age属性看看,注意定义代理后得用代理来调用属性或方法
      console.log(p.age);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

 结果如下,可以发现当我们想输出obj.age时被proxy代理拦截到了,并且我们可以通过代理的get方法自定义实际要返回的是什么。就是说虽然你读取obj.age的值为20,但是我可以通过代理拦截,想返回多少就多少,当然我们上面返回的是真实的值 target[property] :

在这里插入图片描述

2. set方法:

 set(target, property, value, receiver)方法用来拦截某个属性的赋值操作,四个参数依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。看下面例子:

      let obj = { name: "jack", age: "20" };
      let p = new Proxy(obj, {
        set(target, property, value) {
          console.log("要设置对象属性?我拦截到了~");
          console.log("要修改成" + value + "?");
          console.log("我就不给你改,我改成666");
          target[property] = 666;
        },
        get(target, property) {
          return target[property];
        },
      });
      //修改obj.age的值为30;
      p.age = 30;
      //读取obj的age属性看看,注意定义代理后得用代理来调用属性或方法
      console.log(p.age);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

 可以看到,我想修改obj.age为30,但是没成功,因为我在代理拦截set方法里把age值改为666了,所以age值变成了666:
在这里插入图片描述

3.apply方法:

 apply方法能拦截函数的调用、call和apply操作。apply(target, thisArg, argumentsList) 三个参数,分别是目标对象、被调用时的上下文对象、被调用的参数数组。如下:

      function add(a, b) {
        console.log(a + b);
      }
      //给add函数设置一个代理
      let p = new Proxy(add, {
        apply(target, thisArg, argumentsList) {
          console.log("拦截");
          //正常应该如下设置:
          target.apply(this.Arg, argumentsList);
        },
      });
      p(1, 2);
      p.call(null, 13, 22);
      p.apply(null, [5, 3]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

可以看到,函数调用,call调用,apply调用,都执行了代理apply方法里定义的代码:
在这里插入图片描述

4.constructor方法:

  construct(target, argumentsList, newTarget)拦截的是new操作,target目标对象,argumentsList参数列表,newTarget最初被调用的构造函数。简单来说就是拦截new一个构造函数的方法。

      function Animal(name) {
        this.name = name;
      }
      let p = new Proxy(Animal, {
        construct(target, argumentsList, newTarget) {
          //我直接返回一个空对象
          return {};
        },
      });
      //new一个Animal实例
      let dog = new p("dog");
      console.log(dog);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

结果如下,拦截成功,并修改返回:
在这里插入图片描述
下面将不再进行演示,都是大同小异。总的来说Proxy代理能够实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

13种拦截方法如下(以下引用摘自阮一峰ES6入门):

1、get(target, propKey, receiver):

拦截对象属性的读取,比如proxy.foo和proxy[‘foo’]。

2、set(target, propKey, value, receiver): 拦截对象属性的设置,比如proxy.foo =
v或proxy[‘foo’] = v,返回一个布尔值。

3、has(target, propKey):

拦截propKey in proxy的操作,返回一个布尔值。

4、deleteProperty(target, propKey):

拦截delete proxy[propKey]的操作,返回一个布尔值。

5、ownKeys(target):

拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for…in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。

6、getOwnPropertyDescriptor(target, propKey):

拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。

7、defineProperty(target, propKey, propDesc):

拦截Object.defineProperty(proxy, propKey,
propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。

8、preventExtensions(target):

拦截Object.preventExtensions(proxy),返回一个布尔值。

9、getPrototypeOf(target):

拦截Object.getPrototypeOf(proxy),返回一个对象。

10、isExtensible(target):

拦截Object.isExtensible(proxy),返回一个布尔值。

11、setPrototypeOf(target, proto):

拦截Object.setPrototypeOf(proxy,
proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。

12、apply(target, object, args):

拦截Proxy 实例作为函数调用的操作,比如proxy(…args)、proxy.call(object,
…args)、proxy.apply(…)。

13、construct(target, args):

拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(…args)。

三.总结:

 上面就是proxy的一些用法啦。总而言之,Proxy 对象是ES6新出的一个特性,用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。在Vue3中数据劫持原理采用的是Proxy代理。Proxy可以直接监听整个对象而非属性,可以监听数组的变化,具有多达13中拦截方法。
 那么下次见了~
在这里插入图片描述
我的哔哩哔哩空间
Gitee仓库地址:全部特效源码
Q群聊(欢迎):629596039
其它文章:
~关注我看更多简单创意特效:
文字烟雾效果 html+css+js
环绕倒影加载特效 html+css
气泡浮动背景特效 html+css
简约时钟特效 html+css+js
赛博朋克风格按钮 html+css
仿网易云官网轮播图 html+css+js
水波加载动画 html+css
导航栏滚动渐变效果 html+css+js
书本翻页 html+css
3D立体相册 html+css
霓虹灯绘画板效果 html+css+js
记一些css属性总结(一)
Sass总结笔记
…等等
进我主页看更多~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/140144
推荐阅读
相关标签
  

闽ICP备14008679号