ES6新语法之Proxy

目录

定义

 语法

两个参数

handle对象常用的方法(拦截规则)

get   

set

apply

construct

撤销代理对象

Vue为什么要用Proxy重构

Proxy与defineProperty的对比


定义

Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义,如属性查找、赋值、枚举、函数调用等

 语法

new Proxy(target, handle);

两个参数

target是被代理的对象

handle是拦截的规则

const obj = {};
const proxy = new Proxy(obj, {
    // target 目标对象;propKey 属性名;receiver 实例本身;
    get: function(target, propKey, receiver) {
        return 10;
    }
})
console.log(proxy.a); // 打印结果是 10
console.log(proxy.b); // 打印结果是 10
console.log(obj.a); // 打印结果是 undefined
console.log(obj.b); // 打印结果是 undefined

以上代码对obj对象的get操作进行了拦截,任何读取操作都仅会返回10,且该操作只作用在代理对象proxy上,对原对象本身是不起作用的。若obj对象是不可写也不可配置的,代理对象的返回值要与被代理对象的返回值保持一致;若被代理对象没有配置get方位方法,即get方法是undefined,那么返回值必须是undefined。

handle对象常用的方法(拦截规则)

get   

get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。

 1 var person = {
 2   name: "张三"
 3 };
 4 
 5 var proxy = new Proxy(person, {
 6   get: function(target, property) {
 7     if (property in target) {
 8       return target[property];
 9     } else {
10       throw new ReferenceError("Property \"" + property + "\" does not exist.");
11     }
12   }
13 });
14 
15 proxy.name // "张三"
16 proxy.age // 抛出一个错误
set

set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。

 1 let validator = {
 2   set: function(obj, prop, value) {
 3     if (prop === 'age') {
 4       if (!Number.isInteger(value)) {
 5         throw new TypeError('The age is not an integer');
 6       }
 7       if (value > 200) {
 8         throw new RangeError('The age seems invalid');
 9       }
10     }
11 
12     // 对于满足条件的 age 属性以及其他属性,直接保存
13     obj[prop] = value;
14   }
15 };
16 
17 let person = new Proxy({}, validator);
18 
19 person.age = 100;
20 
21 person.age // 100
22 person.age = 'young' // 报错
23 person.age = 300 // 报错

上面代码中,由于设置了存值函数set,任何不符合要求的age属性赋值,都会抛出一个错误,这是数据验证的一种实现方法。利用set方法,还可以数据绑定,即每当对象发生变化时,会自动更新 DOM。 

apply

函数调用捕捉器

construct

new操作符的捕捉器

撤销代理对象

Proxy有一个唯一的静态方法Proxy.revocable(target, handler),可以用来创建一个可撤销的代理对象,该方法的返回值是一个对象,其结构为: {"proxy": proxy, "revoke": revoke}

  • proxy 表示新生成的代理对象本身,和用一般方式 new Proxy(target, handler) 创建的代理对象没什么不同,只是它可以被撤销掉。
  • revoke 撤销方法,调用的时候不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象。

Vue为什么要用Proxy重构

Vue3.0之前,双向绑定主要是由defineProperty实现的。而defineProperty这个方法本身其实是存在不足的,比如说对于对象属性增加、数组按下标修改等一下操作无法做到原生实现。虽然Vue有提供相应的手动observer方法,但在使用体验上还是不尽如人意的。而想较于defineProperty针对属性进行拦截,Proxy直接劫持了整个对象,即不需要对特殊的操作做单独处理。

Proxy与defineProperty的对比

1.Proxy作为新标准,浏览器支持良好

2.Proxy能观察的类型比defineProperty 更丰富

3.Proxy不兼容IE,也没有polyfill,defineProperty 可以支持到IE9

4.defineProperty 劫持对象的属性,当新增属性时,需要再次defineProperty;Proxy直接劫持整个对象,不需要额外操作。

5.defineProperty 在原对象本身进行拦截操作,而Proxy只能在生成的拦截的对象上进行拦截操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值