Proxy

作者: 王小滚 | 来源:发表于2019-04-09 09:44 被阅读0次

代理(Proxy)是一种可以拦截并改变底层js引擎操作的包装器。它在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

创建一个简单的代理

用proxy构造函数创建代理需要传入两个参数:target(目标)和handler(处理程序)。

let target = {};
let proxy = new Proxy(target, {});
proxy.name = 'dudu';
console.log(proxy.name);
console.log(target.name);

target.name = 'lala';
console.log(proxy.name);
console.log(target.name);

这个示例中的代理将所有的操作直接转发到目标,将'dudu'赋值给proxy.name属性时会在target上创建name,代理只是简单的将操作转发给了target,代理本身是不会储存这个属性。

使用set拦截写入属性的操作

问题:一个对象target,它的所有属性的值必须是数字,如果不是数字必须抛出错误。

let target = {
    name: 'dudu';
};
let proxy = new Proxy(target, {
  set(trapTarget, key, value, receiver) {
      // 忽略不希望收到影响的已有元素
      if (!trapTarget.hasOwnProperty(key)) {
          if (isNaN(value)) {
              throw new TypeError("属性必须是数字");
          }
      }
      // 添加属性
      return Reflect.set(trapTarget, key, value, receiver)
  }
});

在该段代码中,我们定义了一个set陷阱来覆写设置属性值得默认特性。set陷阱接受四个参数:

  • trapTarget 用于接收属性(代理的目标)的对象
  • key 要写入的属性键值
  • value 被写入的属性值
  • receiver 操作发生的对象(代理)

使用get拦截读取属性的操作

问题:如果一个属性不存在,让这个对象抛出错误

var person = {
  name: "pangpang"
};

var proxy = new Proxy(person, {
  get: function(target, property) {
    if (property in target) {
      return target[property];
    } else {
      throw new ReferenceError("Property \"" + property + "\" does not exist.");
    }
  }
});

proxy.name // "pangpang"
proxy.age // 抛出一个错误

除了set与get外,还有很多其他的代理陷阱,每个代理陷阱都可以复写js对象的一些内建特性,这里就不一一写出来了。

原型代理陷阱

ES6新增了方法Object.setPrototypeOf()用来改变任意制定对象的原型,以及返回指定对象原型的Object.getPrototypeOf()。通过代理中的setPrototypeOf与getPrototypeOf可以拦截这两个方法的执行过程。在这两种情况下,Object上的方法会调用代理中的同名陷阱来改变方法的行为。

相关文章

网友评论

      本文标题:Proxy

      本文链接:https://www.haomeiwen.com/subject/lbczfqtx.html