Proxy代理拦截器

前言

Proxy 也就是代理,一般叫他拦截器。
Proxy 除读写外还可以监听属性的删除,方法的调用等(delete 对象的属性,给对象的属性赋值等)。
例如对数据的处理,对构造函数的处理,对数据的验证,在访问对象前添加了一层拦截,可以过滤很多操作。

Proxy 区别于 Object.definedProperty。

Object.defineProperty 只能监听到属性的读写,而 Proxy 除读写外还可以监听属性的删除,方法的调用等。

语法

let myProxy = new Proxy(target, handler);
//handler中的三个方法
let myProxy = new Proxy(target, {
	get(target, key) {
      return ***;
    },
    set(target, key, value) {
      return boolean //必须为布尔值
    },
    deleteProperty(target,key){
     return boolean //必须为布尔值
    }
 });

target: 需要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler: 一个对象,其属性是当执行一个操作时定义代理的行为的函数(可以理解为某种触发器)。
handler中有三个方法: get()、set()、deleteProperty()。一旦调用实例的对象时,就会触发这几个方法。但是调用实例不会

特点。

  • set和deleteProperty中的代理拦截设置,只会拦截实例(以下为myProxy )的不正当操作,但不会对target(以下为me)的操作拦截。
  • 修改实例会一起修改target,修改target也会影响实例,相互影响。
  • set和deleteProperty最后必须要返回一个boolean

get获取读写,简单赋值:

  let me = {
    name: "zzz",
    age: "18"
  };
  let myProxy = new Proxy(me, {
    get(target, key) {
      let result = target[key];
      console.log('获取了getter属性');
      if (key === "age") result += "岁";
      return result;
    },
  });
  console.log(me.name);

在这里插入图片描述

上方的案例,我们首先创建了一个me 对象,里面有name属性,然后我们使用Proxy将其包装起来,再返回给myProxy ,此时的myProxy 已经成为了一个Proxy实例,我们对其的操作,都会被Proxy拦截。
Proxy有两个参数,第一个是target,也就是我们传入的*test对象,另一个则是handler,也就是我们传入的第二个参数,一个匿名对象。在handler中定义了一个名叫get的函数,当我们获取 myProxy 的属性时,则会触发此函数。

set拦截

let me = {
    name: "zzz",
    age: "18"
  };
let myProxy= new Proxy(me, {
    get(target, key) {
      let result = target[key];
      //如果是获取 年龄 属性,则添加 岁字
      if (key === "age") result += "岁";
      return result;
    },
    set(target, key, value) {
      if (key === "age" && typeof value !== "number") {
        throw Error("age字段必须为Number类型");
      }
      return Reflect.set(target, key, value);//与target[key] = value; return true;功能一致。 set中return 必须返回的是 boolean值
    }
  });

return Reflect.set(target, key, value);//与target[key] = value; return true;功能一致。 set中return 必须返回的是 boolean值

Reflect传送门滴滴滴,现在还没有

1. 查看myProxy.name和myProxy.age的值

console.log(我叫${myProxy.name} 我今年${myProxy.age}了);
在这里插入图片描述

2. 修改myProxy和修改me的区别

2.1. 将myProxy.age修改为“aa”,无法修改成功,报错。myProxy还是之前的样子。 在这里插入图片描述
由于在myProxy中set中的设置,当myProxy的age不是number类型时,会抛出一个错误throw Error("age字段必须为Number类型");导致myProxy.age无法修改,最后的值还是18岁

2.2. 将myProxy.age修改为17,修改成功
在这里插入图片描述
2.3. 修改target参数,me.age = "eighteen"
明显target的修改不受Proxy中set方法的约数,不管是否为Number类型都可以修改成功。
在这里插入图片描述

综上所述,Proxy中set只会拦截实例(myProxy),过滤对myProxy不正当操作。单并不会影响target(me)的修改。这也证实了,只有调用实例的属性时,才会触发handle

deleteProperty删除拦截

let me = {
    name: "zzz",
    age: "18"
  };
let myProxy= new Proxy(me, {
    get(target, key) {
      let result = target[key];
      //如果是获取 年龄 属性,则添加 岁字
      if (key === "age") result += "岁";
      return result;
    },
	deleteProperty(target,key){
			//设置为只允许删除 a 属性
			if(key === 'name'){
				//对于proxy对象,真正删除的是在deleteProperty中执行
				delete target[key];
				return true;
			}else {
				return target[key];
			}
		}
  });
1. 执行delete myProxy.age;

在这里插入图片描述
由于上述deleteProperty方法定义中,只有当key === 'name'才能删除实例myProxy的属性,所以执行delete myProxy.age;方法被拦截,无法删除

2. 执行delete myProxy.name;

在这里插入图片描述
可以删除

3. 执行delete me.age;

在这里插入图片描述
由于deleteProperty只对实例拦截有效对于target无效,所以在me中可以删除任意属性

对原对象的影响(对target的影响)的影响:

上述在proxy中,myProxy成为了proxy的实例,target是myProxy的参数。

  1. 修改myProxy中的属性
    myProxy.age修改为17后,me.age也变成了17

    在这里插入图片描述

  2. 修改me中的属性
    在对于me.age修改为3后,myProxy中Proxy中age也变成了3
    在这里插入图片描述

    综上所述,互相影响

其他例子:

let arr = [7, 8, 9];
let newArr = new Proxy(arr, {
    set(target, key, val) {
        if (typeof(val) === 'number') {
            target[key] = val
            return true
        } else {
             throw Error("数组必须传入Number类型的值");
        }
    }
})

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值